关于c#:将StreamReader返回开头

Return StreamReader to Beginning

我正在逐行读取文件,并且希望能够通过调用方法Rewind()重新启动读取。

如何操作System.IO.StreamReader和/或其基础System.IO.FileStream以重新开始读取文件?

我有个聪明的主意,就是使用FileStream.Seek(long, SeekOffset)在文件中四处移动,但是包围System.IO.StreamReader却没有任何效果。 我可以Close()并重新分配流和读者引用,但是我希望有更好的方法。


您需要像以前一样在流中进行搜索,然后在StreamReader上调用DiscardBufferedData。此处的文档:

编辑:添加代码示例:

1
2
3
4
5
Stream s = new MemoryStream();
StreamReader sr = new StreamReader(s);
// later... after we read stuff
s.Position = 0;
sr.DiscardBufferedData();        // reader now reading from position 0


我使用这种方法:

1
2
3
4
System.IO.StreamReader reader = new System.IO.StreamReader("file.txt")
//end of reading
reader.DiscardBufferedData();
reader.BaseStream.Seek(0, System.IO.SeekOrigin.Begin);


Amy的答案适用于某些文件,但是根据基础流的编码,您可能会得到意想不到的结果。

例如,如果流是UTF-8并具有前同步码,则StreamReader将使用它来检测编码,然后关闭一些内部标志,告诉它检测编码并检查前同步码。如果将流的位置重置为开始,流阅读器现在将再次使用该前同步码,但是它将第二次将其包含在输出中。没有公共方法可以重置此编码和前导码状态,因此,如果您需要"倒带"流阅读器,最安全的方法是如图所示将基础流搜索到开头(或设置位置)并创建一个新的StreamReader,仅在StreamReader上调用DiscardBufferedData()是不够的。


如果BaseStream实际上可以将Position属性设置为0,那么这一切都很好。

如果不能(例如HttpWebResponse流),那么一个不错的选择是将流复制到MemoryStream ...您可以将Position设置为0并重新启动Stream想。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public long ReadList(string fileName, Action<string> action,long position=0)
{
  if (!File.Exists(fileName)) return 0;

  using (var reader = new StreamReader(File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite),System.Text.Encoding.Unicode))
  {
    if (position > 0)reader.BaseStream.Position = position;

     while (!reader.EndOfStream)
     {
       action(reader.ReadLine());
     }
     return reader.BaseStream.Position;
   }
}


问题是寻找某种StreamReader.Rewind()方法。
您正在寻找StreamReader.BaseStream.Position = 0;,它将阅读器重新设置为开始,以便可以再次阅读。

1
2
3
4
5
6
7
8
9
10
11
12
StreamReader sr = new StreamReader("H:/kate/rani.txt");

Console.WriteLine(sr.ReadToEnd());

sr.BaseStream.Position = 0;

Console.WriteLine("----------------------------------");

while (!sr.EndOfStream)
{
    Console.WriteLine(sr.ReadLine());
}