.NETの改行で文字列を分割する最も簡単な方法は?


806

.NETで文字列を改行に分割する必要があります。文字列を分割する唯一の方法は、Splitメソッドを使用することです。しかし、それは私が(簡単に)改行で分割することを許可しないので、それを行うための最良の方法は何ですか?


2
なぜそうならないのですか?System.Environment.NewLineで分割する
aviraldg

16
しかし、それをstring []でラップし、引数を1つ追加する必要があります。
RCIX、2009年

回答:


1414

文字列を分割するには、文字列の配列を受け取るオーバーロードを使用する必要があります。

string[] lines = theText.Split(
    new[] { Environment.NewLine },
    StringSplitOptions.None
);

編集:
テキスト内のさまざまな種類の改行を処理する場合は、複数の文字列を照合する機能を使用できます。これにより、どちらのタイプの改行でも正しく分割され、テキスト内の空の行とスペースが保持されます。

string[] lines = theText.Split(
    new[] { "\r\n", "\r", "\n" },
    StringSplitOptions.None
);

3
@RCIX:正しいパラメーターをメソッドに送信することは、それが可能なものよりもはるかに単純なものに使用しているため、少し厄介です。少なくとも、それは...あなたは、文字列に分割するために正規表現を使用するか、または独自の分割ルーチンを構築しなければならなかった、そこにフレームワーク2に先立っだ
Guffa

4
@Leandro:Environment.NewLineプロパティには、システムのデフォルトの改行が含まれています。例えば、Windowsシステムの場合、それは次のようになります"\r\n"
Guffa

3
@Leandro:1つの推測では、プログラムは各行の終わりにを\n残して分割し\r、その後、行と行の\r\n間に行を出力します。
Guffa

3
@Samuel:(特に)\rおよび\nエスケープシーケンスは、C#コンパイラにとって特別な意味があります。VBにはこれらのエスケープシーケンスがないため、代わりにこれらの定数が使用されます。
Guffa 2013

2
さまざまなOSのファイルを受け入れる場合は、区切り文字リストの先頭に「\ n \ r」、末尾に「\ r」を追加することもできます。しかし、それがパフォーマンスヒットの価値があるかどうかはわかりません。(en.wikipedia.org/wiki/Newline
user420667

121

使用についてはStringReaderどうですか?

using (System.IO.StringReader reader = new System.IO.StringReader(input)) {
    string line = reader.ReadLine();
}

13
これは私のお気に入りです。拡張メソッドにラップして現在の行を返す:gist.github.com/ronnieoverby/7916886
Ronnie Overby

3
これは私が.netcf 3.5で見つけた唯一の非正規表現ソリューションです
Carl

8
特に入力が大きく、配列全体にコピーすると時間がかかり、メモリを大量に消費する場合に特に便利です。
アレハンドロ

1
書かれているように、この答えは最初の行だけを読みます。この回答に追加する必要があるループについては、Steve Cooperの回答を参照してくださいwhile
ToolmakerSteve

48

次のように、文字列を簡単に分割できるはずです。

aString.Split(Environment.NewLine.ToCharArray());

46
* nix以外のシステムでは、改行文字列の個別の文字(CRおよびLF文字)で分割されます。これにより、各行の間に余分な空の文字列が発生します。
Guffa

私が間違っている場合は修正してください。\とnで分割されませんか?
RCIX、2009年

7
@RCIX:いいえ、\ rおよび\ nコードは単一の文字を表します。文字列「\ r \ n」は4文字ではなく2文字です。
Guffa

10
パラメータStringSplitOptions.RemoveEmptyEntriesを追加すると、これは完全に機能します。
ルーベン

18
@ルーベン:いいえ、それはしません。セルジュは彼の答えですでにそのことを示唆しており、私はすでに、保持する必要のある元のテキストの空の行も削除することをすでに説明しています。
Guffa

34

一般的なソリューションではstring.Splitを使用しないようにしてください。関数を使用するすべての場所で、より多くのメモリを使用するためです。元の文字列と分割コピーの両方がメモリ内にあります。これは、スケーリングを開始するときに問題の1つになる可能性があると私に信じてください。100MBのドキュメントを処理する32ビットのバッチ処理アプリを実行すると、8つの同時スレッドが発生します。以前に行ったことはありません...

代わりに、このようなイテレータを使用してください。

    public static IEnumerable<string> SplitToLines(this string input)
    {
        if (input == null)
        {
            yield break;
        }

        using (System.IO.StringReader reader = new System.IO.StringReader(input))
        {
            string line;
            while( (line = reader.ReadLine()) != null)
            {
                yield return line;
            }
        }
    }

これにより、データの周りでよりメモリ効率の高いループを実行できます。

foreach(var line in document.SplitToLines()) 
{
    // one line at a time...
}

もちろん、すべてをメモリに入れたい場合は、これを行うことができます。

var allTheLines = document.SplitToLines.ToArray();

私はそこに行ったことがあります...(大きなHTMLファイルを解析してメモリが不足しています)はい、string.Splitは避けてください。string.Splitを使用すると、ラージオブジェクトヒープ(LOH)が使用される可能性がありますが、100%確実ではありません。
Peter Mortensen

SplitToLinesを静的メソッド(ddのようです)にした場合、blah.SplitToLines.. たとえば、どうすればよいdocument.SplitToLines...ですか?
Barlop

ああthis、あなたはそれを拡張メソッドにしている仮引数を入れているのを見ます。
Barlop

26

Guffaの回答に基づいて、拡張クラスで次を使用します。

public static string[] Lines(this string source) {
    return source.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None);
}

9

文字列変数の場合s

s.Split(new string[]{Environment.NewLine},StringSplitOptions.None)

これは、環境の行末の定義を使用します。Windowsでは、行末はCR-LF(復帰、改行)またはC#のエスケープ文字\r\nです。

これは信頼できるソリューションです。行をと再結合するとString.Join、これは元の文字列と同じになるためです。

var lines = s.Split(new string[]{Environment.NewLine},StringSplitOptions.None);
var reconstituted = String.Join(Environment.NewLine,lines);
Debug.Assert(s==reconstituted);

してはいけないこと:

  • StringSplitOptions.RemoveEmptyEntries空の行に構文上の目的があるMarkdownなどのマークアップを壊すため、を使用してください。
  • new char[]{Environment.NewLine}Windowsでは、新しい行ごとに1つの空の文字列要素が作成されるため、セパレーターで分割します。

基本的に、ここでは最高評価の受け入れられたものと同じ答えですが、優れた単体テストと警告があります。
vapcguy 2017年

8

正規表現もオプションです:

    private string[] SplitStringByLineFeed(string inpString)
    {
        string[] locResult = Regex.Split(inpString, "[\r\n]+");
        return locResult;
    }

7
空白行を保持しながら、行を正確に一致させたい場合は、次の正規表現文字列が適しています"\r?\n"
Rory O'Kane 2013年

7

この質問の他の解決策は再利用可能なコード分類に分類されず、便利ではないので、2ビットを追加すると思いました。

次のコードブロックは、stringオブジェクトを拡張して、文字列を操作するときに自然なメソッドとして使用できるようにします。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections;
using System.Collections.ObjectModel;

namespace System
{
    public static class StringExtensions
    {
        public static string[] Split(this string s, string delimiter, StringSplitOptions options = StringSplitOptions.None)
        {
            return s.Split(new string[] { delimiter }, options);
        }
    }
}

.Split()これで、次のように任意の文字列の関数を使用できます。

string[] result;

// Pass a string, and the delimiter
result = string.Split("My simple string", " ");

// Split an existing string by delimiter only
string foo = "my - string - i - want - split";
result = foo.Split("-");

// You can even pass the split options parameter. When omitted it is
// set to StringSplitOptions.None
result = foo.Split("-", StringSplitOptions.RemoveEmptyEntries);

改行文字で分割するには、"\n"または"\r\n"を区切り文字パラメーターとして渡します。

コメント: Microsoftがこのオーバーロードを実装したとしたらすばらしいでしょう。


Environment.Newline\nまたはをハードコーディングするよりも推奨されます\r\n
マイケルブラックバーン

3
@MichaelBlackburn-コンテキストがないため、これは無効なステートメントです。Environment.Newline現在のオペレーティングシステムとは異なるラインターミネーションを使用してファイルを操作するためではなく、プラットフォーム間の互換性のためです。詳細についてはこちらを参照してください。開発者が何を扱っているかによって異なります。を使用するとEnvironment.Newline、OS間の改行タイプに一貫性がなくなり、「ハードコーディング」により開発者が完全に制御できるようになります。
Kraang Prime

2
@MichaelBlackburn-あなたが失礼である必要はありません。私は単に情報を提供していました。 .Newlineそれは魔法ではありません。フードの下では、UNIX上で実行されているかWindows上で実行されているかのスイッチに基づいて、上記の文字列にすぎません。最も安全な賭けは、最初にすべての "\ r \ n"に対して文字列置換を行い、次に "\ n"で分割することです。の使用.Newlineが失敗するのは、改行に別の方法を使用する他のプログラムによって保存されたファイルを使用している場合です。読み込まれるファイルが常に現在のOSの改行を使用していることがわかっている場合は、問題なく機能します。
Kraang Prime

だから私が聞いているのは、最も読みやすい方法です(おそらくより高いメモリ使用量)foo = foo.Replace("\r\n", "\n"); string[] result = foo.Split('\n');。これはすべてのプラットフォームで機能することを正しく理解していますか?
John Doe

4

私は現在VB.NETで(他の回答に基づいて)この関数を使用しています:

Private Shared Function SplitLines(text As String) As String()
    Return text.Split({Environment.NewLine, vbCrLf, vbLf}, StringSplitOptions.None)
End Function

最初にプラットフォームローカルの改行で分割を試み、次に可能な各改行にフォールバックします。

これまでのところ、これは1つのクラス内でのみ必要でした。それが変更された場合は、おそらくこれPublicを作成してユーティリティクラスに移動し、拡張メソッドにすることもできます。

適切な方法で、線を元に戻す方法は次のとおりです。

Private Shared Function JoinLines(lines As IEnumerable(Of String)) As String
    Return String.Join(Environment.NewLine, lines)
End Function

@Samuel-引用に注意してください。彼らは実際にその意味を持っています。"\r"=戻る。 "\r\n"= return + new line。(この投稿とここで承認された解決策
Kraang Prime

@Kraangうーん..私は長い間.NETで働いていません。多くの人が間違った答えに投票したとしたら、私は驚きます。私もグッファの答えにコメントし、そこに明確化したことがわかります。この回答へのコメントを削除しました。ヘッドアップをありがとう。
サミュエル

2

さて、実際に分割する必要があります:

//Constructing string...
StringBuilder sb = new StringBuilder();
sb.AppendLine("first line");
sb.AppendLine("second line");
sb.AppendLine("third line");
string s = sb.ToString();
Console.WriteLine(s);

//Splitting multiline string into separate lines
string[] splitted = s.Split(new string[] {System.Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries);

// Output (separate lines)
for( int i = 0; i < splitted.Count(); i++ )
{
    Console.WriteLine("{0}: {1}", i, splitted[i]);
}

2
RemoveEmptyEntriesオプションは、テキストから空の行を削除します。これは状況によっては望ましいかもしれませんが、単純な分割は空の行を保持する必要があります。
Guffa

はい、そうです、私はこの仮定をしただけです。つまり、空白行はおもしろくないです;)
MaciekTalaska '10年

1
string[] lines = text.Split(
  Environment.NewLine.ToCharArray(), 
  StringSplitOptions.RemoveEmptyStrings);

RemoveEmptyStringsのオプションは、\ rの次に起因\ nまでの空のエントリを持っていないことを確認します

(コメントを反映するように編集します。)また、テキスト内の純粋な空行も破棄されます。これは通常私が欲しいものですが、あなたの要件ではないかもしれません。


RemoveEmptyStringsオプションも空の行を削除するため、テキストに空の行が含まれていると正しく機能しません。
Guffa

\ rを\ nは\ rを\ nは:あなたは、おそらく本物の空行を保持したい
スリム

0

Environment.Newlineについては知りませんでしたが、これは非常に良い解決策だと思います。

私の試みはされていたでしょう:

        string str = "Test Me\r\nTest Me\nTest Me";
        var splitted = str.Split('\n').Select(s => s.Trim()).ToArray();

追加の.Trimは、まだ存在する可能性のある\ rまたは\ nをすべて削除します(たとえば、ウィンドウ上にあるが、文字列をos x改行文字で分割する場合)。おそらく最速の方法ではありません。

編集:

コメントが正しく指摘したように、これにより、行の先頭または新しい改行の前にある空白も削除されます。その空白を保持する必要がある場合は、他のオプションのいずれかを使用してください。


トリムは、インデントなど、行の最初と最後の空白も削除します。
Guffa

「.Trimは、まだ存在している可能性がある\ rまたは\ nを削除します」-痛い。代わりに堅牢なコードを書いてみませんか?
bzlm

たぶん私は質問を間違えましたが、空白を保持する必要があることは明らかでした/明確ではありません。もちろん、あなたの言う通り、Trim()は空白も削除します。
最大

1
@マックス:わあ、仕様で明確に除外されていないことをコードが実行できることを上司に伝えるまで待ちます...;)
Guffa

-2

ばかげた答え:由緒あるものを使用できるように一時ファイルに書き込む File.ReadLines

var s = "Hello\r\nWorld";
var path = Path.GetTempFileName();
using (var writer = new StreamWriter(path))
{
    writer.Write(s);
}
var lines = File.ReadLines(path);

1
var変数のタイプを定義していないので、を避けてください。そのオブジェクトの使用方法や、そのオブジェクトが何を表しているのか理解できない場合があります。さらに、これは行の書き込みを示しており、ファイル名も指定していないため、うまくいくとは思えません。次に、読み取り時に、ファイルへのパスが再び指定されません。それpathがそうC:\Temp\test.txtであると仮定すると、あなたは持っているべきstring[] lines = File.ReadLines(path);です。
vapcguy 2017年

1
@vapcguy何を読んだの?-あなたが言ったすべてが明らかに間違っているので、投稿をもう一度読むか、コンソールプログラムでデバッグすることをお勧めします。パスがPath.GetTempFileNameに設定されている| varはC#で一般的で推奨される定義です。変数の型を定義する方法です……編集:これは良い解決策とは言えません
koanbock

[OK]を@koanbockので、私は見上げPath.GetTempFileName msdn.microsoft.com/en-us/library/...をし、それが言うことは、ゼロバイトのファイル&リターン「そのファイルのフルパス」を作成します。私は以前にこれを試したと誓うことができました、そしてそれはそれがファイルを見つけなかったので例外を与えましたが、代わりにフォルダの場所が返されました。私はの使用に関する引数を知っvarていますが、変数オブジェクトが何であるかを示していないため、お勧めしません。難読化します。
vapcguy

-3
using System.IO;

string textToSplit;

if (textToSplit != null)
{
    List<string> lines = new List<string>();
    using (StringReader reader = new StringReader(textToSplit))
    {
        for (string line = reader.ReadLine(); line != null; line = reader.ReadLine())
        {
            lines.Add(line);
        }
    }
}

-5

実はとても簡単です。

VB.NET:

Private Function SplitOnNewLine(input as String) As String
    Return input.Split(Environment.NewLine)
End Function

C#:

string splitOnNewLine(string input)
{
    return input.split(environment.newline);
}

4
完全に正しくなく、機能しません。さらに、C#ではEnvironment.NewLine、VBと同じです。
vapcguy 2017年

VB.NETの行末識別子を参照してください新しい行のさまざまなオプション。
Peter Mortensen
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.