c#FileStream Read与StreamReader EndOfStream存在问题

c#FileStream Read与StreamReader EndOfStream存在问题,c#,filestream,streamreader,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个字母作为字节,其余的作为字符串。在查找资料并进

正如标题所说,我发现了一个问题。首先是小背景故事: 我们的
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
中。这只是一行。如果我们在添加
的同时添加

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个字符作为字节,其余的是字符串,这对每一行都是一样的


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

这里的问题是简单的缓冲。将
StreamReader
附加到
FileStream
时,它会消耗文件中的一个块,从而提升
FileStream
的当前
位置。使用示例文件和默认缓冲区大小,一旦
StreamReader
连接自身,它基本上会将整个文件消耗到缓冲区中,使
FileStream
处于其EOF。然后,当您试图通过
fs
引用直接从
FileStream
中读取4个字节时,就没有什么可消耗的了。以下
ReadLine
适用于从缓冲文件内容读取的
sr
引用

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

  • fs
    打开文件并位于
    位置
    0
  • sr
    fs
    打包,对
    EndOfStream
    的调用(在本例中)将27个字节消耗到其内部缓冲区中。此时,
    fs
    位置现在位于EOF
  • 您试图直接从
    fs
    读取,但它在EOF时没有更多字节
  • sr.ReadLine
    从它在步骤2中建立的缓冲区中读取数据,所有这些都工作正常
  • 要修复特定的错误情况,可以将字节数组更改为字符数组,并改用
    sr.Read
    。i、 e

    char[] arr = new char[4];
    sr.Read(arr, 0, 4);
    
    现在有个问题了。现在,arr什么也没有得到,s读整行,包括前4个字母

    是的,这似乎很有道理
    StreamReader
    维护一个缓冲区—当您要求它读取一行文本时,它很可能会从流中读取比那一行更多的内容,在下次要求它提供信息时使用缓冲数据

    基本上,我强烈建议不要直接从
    StreamReader
    正在读取的流中读取。即使在可能的情况下,也很难做到正确,在某些情况下,API可能不允许您做您想做的事情


    如果要从每行中删除前四个字符,则更简单的方法是读取整行,然后使用
    Substring

    fs
    中读取数组,然后从
    sr
    中读取其余行。谢谢。我只想说,这似乎是因为这种消费只发生在sr使用或类似的东西。这就是为什么在sr初始化时,仍然可以使用fs.Read(),但在sr.ReadLine()或sr.EndOfStream之后,fs.Read()将停止给出结果。也是的,我删除了它,因为我做了一些错误的测试,并假设了错误的事实。所以为了不保留虚假信息,我决定删除它。