c#FileStream读取StreamReader EndOfStream存在问题

时间:2017-08-18 07:09:05

标签: c# filestream streamreader

正如标题所说,我发现了一个问题。小故事第一: 我们file.txt看起来像这样:

aaaabb
ccccddd
eeeefffffff

有许多方法可以逐行阅读此文本,其中一种方法是:

StreamReader sr = new StreamReader("file.txt");
while(!sr.EndOfStream)
{
    string s = sr.ReadLine();
}
sr.Close();

作品。获得每一行s。 现在我需要前4个字母作为字节,其余的作为字符串。在查看事物并尝试一点之后,我发现最简单的方法就是:

FileStream fs = new FileStream("file.txt", FileMode.Open);
StreamReader sr = new StreamReader(fs);
byte[] arr = new byte[4];
fs.Read(arr, 0, 4);
string s = sr.ReadLine();
sr.Close();
fs.Close();

作品。 arr包含前4个字母作为字节,其余部分保存在s中。这只是一行。如果我们添加while

FileStream fs = new FileStream("file.txt", FileMode.Open);
StreamReader sr = new StreamReader(fs);
while(!sr.EndOfStream)
{
    byte[] arr = new byte[4];
    fs.Read(arr, 0, 4);
    string s = sr.ReadLine();
} 
sr.Close();
fs.Close();

现在有问题了。现在arr没有得到任何内容,s读取整行,包括前4个字母。更奇怪的是,如果我使用while(true)(我假设其他任何不是示例)而不是按预期工作,则4个字符作为字节,其余为字符串,这对于每一行都是相同的。

问题是我错过了什么?为什么会这样?我该如何解决这个问题?或者这可能是一个错误?

2 个答案:

答案 0 :(得分:7)

这里的问题是简单的缓冲。当您将StreamReader附加到FileStream时,它最终会占用文件中的一个块,从而推进Position的当前FileStream。使用您的示例文件和默认缓冲区大小,一旦StreamReader附加自身,它基本上将整个文件消耗到缓冲区中,使FileStream保持在其EOF。当您尝试直接通过FileStream引用从fs读取4个字节时,没有什么可以消耗的。以下ReadLine适用于sr引用,因为它是从缓冲文件内容中读取的。

以下是对正在发生的事情的逐步细分:

  1. fs打开文件并位于Position 0。
  2. sr包裹fs,对EndOfStream的调用最终消耗(在本例中)27个字节到其内部缓冲区。此时,fs Position现在位于EOF。
  3. 您尝试直接从fs读取,但在EOF中没有更多字节。
  4. sr.ReadLine从步骤#2中构建的缓冲区中读取,一切正常。
  5. 要修复特定的错误情况,可以将字节数组更改为char数组,然后使用sr.Read。即。

    char[] arr = new char[4];
    sr.Read(arr, 0, 4);
    

答案 1 :(得分:4)

  

现在出现了问题。现在arr并没有得到任何东西,并且s读取整行,包括前4个字母。

是的,这似乎很合理。 StreamReader维护一个缓冲区 - 当你要求它读取一行文本时,它可能会从流中读取 more 而不是单行,使用缓冲后的数据接下来要求提供信息。

从根本上说,我强烈建议直接从流中读取StreamReader正在读取的内容。即使在可能的情况下,它也会变得非常繁琐,在某些情况下,API可能不会让你做你想做的事。

如果你想从每一行中删除前四个字符,那么读取整行就会 更简单,然后使用Substring