[C#] 文字列を改行コードで1行ずつに分割する方法

2024-08-09 (金)

LF, CRLF などの改行コードで1行ずつの文字列を分割して取得する方法です。

環境

  • .NET 8.0.7 (SDK 8.0.303)
  • C# 12.0
  • Visual Studio 2022 Version 17.10.5
  • Windows 11 Pro 23H2 22631.3880

EnumerateLines() で1行ずつ列挙する

MemoryExtensions.EnumerateLines() を使用する例です。.NET 6 以降で利用可能です。

string[] にする必要がなければ、foreach で処理できます。

string text = GetSampleText();

foreach (var line in text.AsSpan().EnumerateLines())
{
    // line が ReadOnlySpan<char> なので、string にしたければ ToString() で変換
    Console.WriteLine(line.ToString());
}

EnumerateLines() で分割して配列にする

次に、string[] にする必要がある場合です。

public static string[] SplitLines(ReadOnlySpan<char> span)
{
    using var builder = new ValueArrayBuilder<string>();

    foreach (var element in span.EnumerateLines())
    {
        builder.Add(element.ToString());
    }

    return builder.ToArray();
}

ValueArrayBuilderList<string> に置き換えても問題ありません。
詳しくは以下の記事を参照してください。

[C#] ArrayPool を使用して ToArray のアロケーションを1回にする方法

一般的には List<T> を使用して要素を追加して行き、最後に ToArray() することで配列を作成します。
この方法では、最後の配列以外に作業用のヒープメモリ確保が発生してしまいます。
プールと構造体を使用することで、最後の完成した配列に対して1回のみメモリ確保する実装例です。

C# C# パフォーマンス 2024-08-08 (木)

Split() で分割する

String.Split を使用する例です。

private static readonly string[] NewLineStrings = ["\r\n", "\n"];

public static string[] SplitLines(string value)
{
    return text.Split(NewLineStrings, StringSplitOptions.None);
}

CRLFLF が混在していても対応できるように、両方指定しています。ただし、それ以外の改行コードは考慮していません。

💡 前述の EnumerateLines() は、CRLFLF 以外の改行コードにも対応しています。

2024-08-09 (金)