【问题标题】:Read lines in C# without losing newline characters在 C# 中读取行而不丢失换行符
【发布时间】:2019-03-21 15:48:52
【问题描述】:

目前,我正在使用 C# 的内置 StreamReader 从文件中读取行。

众所周知,如果最后一行是空白的,则流读取器不会将其视为单独的行。也就是说,一行必须包含文本,最后一行的换行符是可选的。

这对我的一些文件产生影响,每次我的程序消耗和重写特定文件时,我在文件末尾丢失了一些文件(很重要,因为我不想进入)。

是否有TextReader 的实现作为语言的一部分或作为提供ReadLine 功能的NuGet 包提供,但保留换行符(无论它们可能是)作为行的一部分这样我就可以准确地重现输出?我宁愿不必使用自己的方法来使用基于行的输入。

编辑:应该注意我无法将整个文件读入内存。

【问题讨论】:

  • 如果您想阅读换行符,请使用StreamReader.Read() 而不是ReadLine() 并累积对您很重要的字符。
  • @DourHighArch 是的,我可以这样做 - 但是我想检查这个(我认为)明显的情况是否已经以包装的方式处理(例如,作为 TextReader 的实现,根据问题)。
  • 这不是 StreamReader 的工作方式,您可以从文本文件中的尾随空行中获取空字符串。修复错误,而不是类。
  • @Hans,我不敢苟同,因为这正是我观察到的行为。使用包含 3 行文本的文本文件,最后一行没有任何内容(不以换行符终止),我看到三行文本,然后流阅读器返回 null。
  • 您对文本查看器/编辑器的工作方式感到困惑。只需将其简化为基础,使用编辑器创建一个文本文件,不要输入任何内容,只需按 Enter 键。验证 StreamReader 将返回一个空字符串,然后返回 null。

标签: c# string


【解决方案1】:
private readonly char newLineMarker = Environment.NewLine.Last();
private readonly char[] newLine = Environment.NewLine.ToCharArray();
private readonly char eof = '\uffff';

private IEnumerable<string> EnumerateLines(string path)
{
    using (var sr = new StreamReader(path))
    {
        char c;
        string line;
        var sb = new StringBuilder();

        while ((c = (char)sr.Read()) != eof)
        {
            sb.Append(c);
            if (c == newLineMarker &&
                (line = sb.ToString()).EndsWith(Environment.NewLine))
            {
                yield return line.Trim(newLine);

                sb.Clear();
                sb.Append(Environment.NewLine);
            }
        }

        if (sb.Length > 0)
            yield return sb.ToString().Trim(newLine);
    }
}

【讨论】:

  • 我不得不说,你这样做给我留下了深刻的印象......我明天会试试看它是否有效!
  • 祝你好运!我测试了代码,所以我确信它应该可以工作。
  • 我将其标记为正确,因为它允许我生成更成熟的解决方案。
  • 太棒了!很高兴你!
【解决方案2】:

您可以将ReadToEnd()Split 结合起来,以数组形式获取文件的内容,包括空行。

如果你的文件很大,我不建议你使用ReadToEnd()

例如:

string[] lines;

using (StreamReader sr = new StreamReader(path)) 
{
    var WholeFile = sr.ReadToEnd();
    lines = WholeFile.Split('\n');
}

【讨论】:

  • 这会起作用,但是有些文件非常大,不适合这样的内存。抱歉,我没有包含该详细信息!
  • @PhilipAdler 自己用docs.microsoft.com/en-us/dotnet/api/…自定义分块怎么样?
  • @kenny 分块是我的第二个选择。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-09
  • 1970-01-01
相关资源
最近更新 更多