3

またはで使用ReadLine()すると、ファイルまたは文字列が改行で終わる場合、その文字シーケンスが完全に失われることに気付きました。次の例を検討してください。StreamReaderStringReader

static void Main(string[] args)
{
    string data = "First Line\r\nSecond Line\r\n\r\n\r\n";
    List<string> lineData = new List<string>();
    string[] splitData = data.Split(
        new string[] { "\r\n" }, 
        StringSplitOptions.None);

    using (StringReader sr = new StringReader(data))
    {
        string line;
        while ((line = sr.ReadLine()) != null)
            lineData.Add(line);
    }

    Console.WriteLine("Raw Line Count: " + splitData.Length);
    Console.WriteLine("StringReader Line Count: " + lineData.Count);
    Console.WriteLine("Split Data: ");
    foreach (string s in splitData)
        Console.WriteLine(string.IsNullOrEmpty(s) ? "[blank line]" : s);
    Console.WriteLine("StringReader Data: ");
    foreach (string s in lineData)
        Console.WriteLine(string.IsNullOrEmpty(s) ? "[blank line]" : s);
    Console.ReadKey();
}

出力は次のとおりです。

Raw Line Count: 5
StringReader Line Count: 4
Split Data:
First Line
Second Line
[blank line]
[blank line]
[blank line]
StringReader Data:
First Line
Second Line
[blank line]
[blank line]

StringReader/StreamReaderがこのように動作するのはなぜですか? 回避策はいくつか考えられますが、リーダーが予期しない動作をするためにコードを修正しなければならないのはばかげているように思えます。ストリームが最終的な改行を処理する方法に影響を与える .NET ライブラリの設定はありますか?

編集

別の例を次に示します。この例を最初に実行したときの結果"First Line\r\nSecond Line"と、次に に対して実行したときの結果を比較します"First Line\r\nSecond Line\r\n"。結果はまったく同じです (例の StringReader 部分に関する限り)。null空の文字列ではなく、2 番目の例でStringReader が返されるのはなぜですか? から返される文字列に改行が含まれていないことは承知していますが、最後の行が ?の代わりにReadLine()解釈されるのはなぜですか?null""

4

3 に答える 3

3

出力の違いは、の奇妙な動作によるものではありませんStringReader。入力には4行しか含まれておらず、正確に4行が読み取られていることに注意してください(ドキュメントで指定されているように、最後の改行トークンなしでのみ)。余分な行を導入するのはSplitメソッドです。空のエントリを保持したい場合は、最後のトークンの後に存在しないエントリが作成されるためです。

の出力StringReader:

"First Line\r\nSecond Line\r\n\r\n\r\n";
 ^1st          ^2nd           ^3rd^4th   (line)

の出力Split:

"First Line\r\nSecond Line\r\n\r\n\r\n";
 ^1st          ^2nd           ^3rd^4th^5th (token)

次の入力を検討してください。

"First line\r\n"

何行ですか?1 つ、それが出力です。

Split Data:
First Line
[blank line]
StringReader Data:
First Line

ですから、ここでSplit「問題」(ある場合)はそこにあるようです。

本当の問題は、以下のコメントでDouglasによって説明されました。ただし、インターフェースの典型的な使用例では、それは気にしません。気にしたい場合は、少し低いレベルのインターフェイスを使用する必要があります (例: Read )。"ABC\r\nXYZ""ABC\r\nXYZ\r\n"ReadLine

于 2013-10-14T17:15:01.237 に答える
2

これは予想される動作であり、文書化されています。から - http://msdn.microsoft.com/en-us/library/system.io.stringreader.readline.aspx

行は、一連の文字の後にライン フィード ("\n")、キャリッジ リターン ("\r")、またはキャリッジ リターンの直後にライン フィード ("\r\n") が続くものとして定義されます。返される文字列には、終了のキャリッジ リターンまたはライン フィードは含まれません。文字列の末尾に到達した場合、戻り値は null です。

返された最後の値が null であり、最後の改行が省略されることを意味します。読み取りデータに表示する必要がある場合は、 uisng で再申請できますEnvironment.NewLine

于 2013-10-14T17:12:01.537 に答える
2

のドキュメントごとReadLine:

行は、一連の文字の後にライン フィード ("\n")、キャリッジ リターン ("\r")、またはキャリッジ リターンの直後にライン フィード ("\r\n") が続くものとして定義されます。返される文字列には、終了のキャリッジ リターンまたはライン フィードは含まれません。入力ストリームの最後に到達した場合、戻り値は null です。

Environment.NewLine入力ストリームをトークン化し、結果を返すために依存するメソッドを使用しています。これらのトークンは結果から除外されるため、予想される動作が表示されているものであることは当然です。

これらの文字が必要な場合は、ファイルをチャンクで読み取り (Readバッファー付きの標準を使用)、コンテンツを自分で分割することをお勧めします。Streamまたは、必要に応じてタスクを実行するの独自の実装を作成することもできます。

于 2013-10-14T17:14:12.877 に答える