web-dev-qa-db-ja.com

StreamオブジェクトのReadAllLines?

File.ReadAllLinesは存在しますが、Stream.ReadAllLinesは存在しません。

using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Test_Resources.Resources.Accounts.txt"))
using (StreamReader reader = new StreamReader(stream))
{
    // Would prefer string[] result = reader.ReadAllLines();
    string result = reader.ReadToEnd();
}

これを行う方法はありますか、またはファイルを1行ずつ手動でループする必要がありますか?

55
Ryan Peschel

次のように、行ごとに読み取るメソッドを作成できます。

public IEnumerable<string> ReadLines(Func<Stream> streamProvider,
                                     Encoding encoding)
{
    using (var stream = streamProvider())
    using (var reader = new StreamReader(stream, encoding))
    {
        string line;
        while ((line = reader.ReadLine()) != null)
        {
            yield return line;
        }
    }
}

次に、次のように呼び出します。

var lines = ReadLines(() => Assembly.GetExecutingAssembly()
                                    .GetManifestResourceStream(resourceName),
                      Encoding.UTF8)
                .ToList();

Func<>パートは、複数回読み取るときに対処し、ストリームを不必要に開いたままにしないようにすることです。もちろん、そのコードをメソッドに簡単にラップできます。

一度にすべてをメモリに保存する必要がない場合は、ToList...も必要ありません。

96
Jon Skeet

.EndOfStreamプロパティは、次の行がnullでないかどうかをチェックする代わりに、ループで使用できます。

List<string> lines = new List<string>();

using (StreamReader reader = new StreamReader("example.txt"))
{
    while(!reader.EndOfStream)
    {
        lines.Add(reader.ReadLine());
    }
}
35
Bryan Johnson

ここでのSplitの使用:

reader
   .ReadToEnd()
   .Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);

ReadLineと同等ではありません。 ReadLineStreamReader.cs のソースを見ると、行終端文字(\ r、\ n、および\ r\n)を正しく処理していることがわかります。 ReadLineは、行末記号が\ r\nの場合、余分な空の文字列を返しません。これはDOS/Windowsで一般的です。 Splitは、\ rの後に2つの個別の区切り文字として「見える」(解析する)もので、空の文字列を返します。

上記のコードの「StringSplitOptions.RemoveEmptyEntries」はこれらの空の文字列を削除しますが、入力に表示される空の行も削除します。

したがって、入力に対してline1\r\r line3\r ReadLineは3行を返します。 2番目は空です。 Splitは4つの文字列を作成します。 (最後の\ rの後に追加の文字列があります。)2番目と4番目を削除します。

Splitは、「修正後」で区切られたテキスト行の解析にはあまり適していません。それは、トークンの後に表示される区切り文字です。 Splitは中置に適していますが、区切り文字はトークン間にあります。これは、a、b、cとline1\r、line2、line3\rの違いです。これらの入力に対して、Splitはそれぞれ3つの文字列または4つの文字列を返します。

6
Andrew Dennison
using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Test_Resources.Resources.Accounts.txt"))
using (StreamReader reader = new StreamReader(stream))
{
    // Would prefer string[] result = reader.ReadAllLines();
    string[] result = reader.ReadToEnd().Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
}
6
Steve Danner

次の拡張メソッドを使用します。

public static class Extensions
{
    public static IEnumerable<string> ReadAllLines(this StreamReader reader)
    {
        string line;
        while ((line = reader.ReadLine()) != null)
        {
            yield return line;
        }
    }
}

目的のコードに到達することが可能です。

using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Test_Resources.Resources.Accounts.txt"))
using (StreamReader reader = new StreamReader(stream))
{
    string[] result = reader.ReadAllLines().ToArray();
}
0
Fidel

StreamReaderを使用する場合は、ReadLineを使用してStreamReaderをループ処理し、1行ずつ読み取る必要があります。

そんな感じ:

string line;

using (StreamReader reader = new StreamReader(stream))
{
    while ((line = reader.ReadLine()) != null)
    {   
        Console.WriteLine(line); 
    }
}

または試す

using (StreamReader reader = new StreamReader("file.txt"))
    {

       string[] content = reader.ReadToEnd().Replace("\n","").Split('\t');
    }
0
Coding Duchess