为什么StreamReader.ReadLine()为没有换行的一行文件返回一个值?

时间:2010-08-10 02:07:57

标签: c# readline streamwriter

我想将两个文本文件附加在一起。

我有一个文件,末尾有回车换行符。观察文件A,即28个字节。

  

这是文件\ n

中的一行

然后我有另一个文件,没有新行是相同的。观察文件B,即26个字节。

  

这是文件中的一行

我想将相同的文件附加到自身(文件A到A,文件B到B)并比较字节数。

但是,在文件A上使用StreamReader.ReadLine()时,我会返回一个值,但MSDN说:

  

一行被定义为字符序列,后跟换行符(“\ n”),回车符(“\ r”)或回车符后紧跟换行符号(“\ r \ n”) )。返回的字符串不包含终止回车符或换行符。如果到达输入流的末尾,则返回值为null。

但是,文件中没有crlf。

如何在不添加额外换行符的情况下安全地附加这些文件?例如,当我不想要它时,StreamWriter.WriteLine()会在文件A上放置额外的换行符。什么是理想的方法?

4 个答案:

答案 0 :(得分:3)

如果您在流媒体结束时调用null ,则只会获得ReadLine。否则,您将获得所有数据,直到 CRLF 流的末尾。

如果您尝试进行逐字节重复(和比较),最好先阅读这两个字符(现在使用StreamReader / StreamWriter)或字节(仅使用Stream类)使用普通ReadWrite函数,而不是ReadLineWriteLine

您也可以使用ReadToEnd读取文件的全部内容,然后通过调用Write(而不是WriteLine)来编写它,但如果文件很大,这是不切实际的

string data;

using(StreamReader reader = new StreamReader(path))
{
    data = reader.ReadToEnd();
}

using(StreamWriter writer = new StreamWriter(path, true))
{
    writer.Write(data);
}

答案 1 :(得分:2)

您可以使用StreamWriter.Write而不是WriteLine来避免额外的crlf。

对于ReadLine文档,我相信这个问题是措辞不当的解释。您当然不希望丢弃文件的最后一个字节只是因为没有正式的行结束标志。

答案 2 :(得分:2)

StreamReader和StreamWriter(派生自TextReader和TextWriter)不适合需要精确形式的二进制数据的情况。它们是文件的高级抽象,由字节组成,而不是文本或行。实际上,您不仅可以使用不同数量的换行符,而且根据环境,您可能会写出除预期CR / LF之外的行终止符。

您应该只从一个流复制到另一个流。实际上这很容易。

var bytes = File.ReadAllBytes(pathIn);
var stream = File.Open(pathOut, FileMode.Append);
stream.Write(bytes, 0, bytes.Length);
stream.Close();

如果文件的大小可能很大,您应该同时打开输入和输出文件,并使用固定大小的缓冲区一次复制一个块。

using (var streamIn = File.Open(pathIn, FileMode.Read))
using (var streamOut = File.Open(pathOut, FileMode.Append)) {

    var bytes = new byte[BLOCK_SIZE];

    int count;
    while ((count=streamIn.Read(bytes, 0, bytes.Length)) > 0) {
        streamOut.Write(bytes, 0, count);
    }

}

另外值得注意的是,上面的代码可以替换为.NET 4中新增的Stream.CopyTo

答案 3 :(得分:0)

那真的取决于你实现的原因(你为什么要逐行阅读并逐行写回来?)你可以使用StreamWriter.Write(string)并输出你存储的所有文本,{ {3}}方法是这样命名的,因为它们附加了换行符。

  

TextWriter.WriteLine方法(字符串)
  将一个字符串后跟一个行终止符写入文本流。