我怎么知道文本文件是否以回车符 return 结尾?

How can I know if a text file ends with carriage return or not?

我必须处理一个文本文件并检查它是否以回车符结尾 return。

我必须阅读全部内容,进行一些更改并将其重新写入目标文件,并保持与原始格式完全相同的格式。问题是:我不知道原始文件最后是否包含换行符。

我已经试过了:

如何有效地读取文件的所有文本并确定它是否以换行符结尾?

通过ReadLine()读取文件后,您可以返回到文件末尾之前的两个字符并将这些字符与CR-LF:

进行比较
string s;
using (StreamReader sr = new StreamReader(@"C:\Users\User1\Desktop\a.txt", encoding: System.Text.Encoding.UTF8))
{
    while (!sr.EndOfStream)
    {
        s = sr.ReadLine();
        //process the line we read...
    }

    //if (sr.BaseStream.Length >= 2) { //ensure file is not so small

    //back 2 bytes from end of file
    sr.BaseStream.Seek(-2, SeekOrigin.End);

    int s1 = sr.Read(); //read the char before last
    int s2 = sr.Read(); //read the last char 
    if (s2 == 10) //file is end with CR-LF or LF ... (CR=13, LF=10)
    {
        if (s1 == 13) { } //file is end with CR-LF (Windows EOL format)
        else { } //file is end with just LF, (UNIX/OSX format)
    }

}

所以你正在处理一个文本文件,这意味着你需要读取所有文本,并希望保留任何换行符,即使在文件末尾也是如此。

您正确地得出结论 ReadLine() 吃掉了那些文件,即使文件不以 one 结尾。事实上,当文件以 1 结尾时,ReadLine() 吃掉了最后一个 return(StreamReader.EndOfStream 在读取倒数第二行后是 true)。 ReadAllText() also eats the last newline。考虑到您可能要处理大文件,您也不想一次读取内存中的整个文件。

你也不能只比较文件的最后两个字节,因为有些编码使用多个字节来编码一个字符,例如UTF-16。所以你需要阅读文件encoding-aware。 StreamReader 就是这样做的。

因此,一个解决方案是创建您自己的 ReadLine() 版本,其中包括末尾的换行符:

public static class StreamReaderExtensions
{
    public static string ReadLineWithNewLine(this StreamReader reader)
    {
        var builder = new StringBuilder();

        while (!reader.EndOfStream)
        {
            int c = reader.Read();

            builder.Append((char) c);
            if (c == 10)
            {
                break;
            }
        }

        return builder.ToString();
    }
}

然后你可以检查最后一个 returned 行是否以 \n:

结尾
string line = "";

using (var stream = new StreamReader(@"D:\Temp\NewlineAtEnd.txt"))
{
    while (!stream.EndOfStream)
    {
        line = stream.ReadLineWithNewLine();
        Console.Write(line);
    }
}

Console.WriteLine();

if (line.EndsWith("\n"))
{
    Console.WriteLine("Newline at end of file");
}
else
{
    Console.WriteLine("No newline at end of file");
}

虽然 StreamReader 进行了大量优化,但我不能保证一次读取一个字符的性能。与 ReadLine()(~1800 vs ~400 毫秒)相比,使用两个相等的 100 MB 文本文件进行的快速测试显示速度明显下降。

虽然这种方法确实保留了原始行尾,这意味着您可以使用通过这种扩展方法 return 编辑的字符串安全地重写文件,而无需将所有 \n 更改为 \r\n 或反之亦然。