75

存在 aFile.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();
}

有没有办法做到这一点,还是我必须逐行手动循环文件?

4

6 回答 6

119

您可以编写一个逐行读取的方法,如下所示:

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...

于 2012-11-09T17:27:03.607 回答
47

.EndOfStream属性可以在循环中使用,而不是检查下一行是否不为空。

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

using (StreamReader reader = new StreamReader("example.txt"))
{
    while(!reader.EndOfStream)
    {
        lines.Add(reader.ReadLine());
    }
}
于 2013-12-12T16:04:43.327 回答
7
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);
}
于 2012-11-09T17:27:03.890 回答
6

这里的使用Split

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

不等于ReadLine。如果您查看StreamReader.csReadLine的源代码,您会发现它正确处理了行终止符:\r、\n 和 \r\n。当行终止符为 \r\n 时,不会返回额外的空字符串,这在 DOS/Windows 中很常见。“看到”(解析) \r 后跟 \n 作为 2 个单独的分隔符并返回一个空字符串。ReadLineSplit

上面代码中的“StringSplitOptions.RemoveEmptyEntries”确实删除了这些空字符串,但它也会删除输入中出现的任何空行。

因此对于输入 line1\r \r line3\r ReadLine返回 3 行。第二个是空的。 Split创建 4 个字符串。(在最后一个 \r 之后有一个附加字符串。)然后它会删除第 2 个和第 4 个。

请注意,Split它不太适合解析“后修复”分隔的文本行。即分隔符出现在标记之后。WhileSplit适用于中缀,分隔符出现在标记之间。它是 a,b,c 和 line1\r,line2,line3\r 之间的区别。对于这些输入,Split分别返回 3 个字符串或 4 个字符串。

于 2014-05-22T03:35:22.120 回答
1

使用以下扩展方法:

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();
}
于 2018-12-22T15:41:03.510 回答
0

如果你想使用 StreamReader 那么是的,你将不得不使用 ReadLine 并循环通过 StreamReader,逐行读取。

像这样的东西:

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');
    }
于 2012-11-09T17:29:18.080 回答