将StreamReader返回到开始


74

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

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

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

Answers:


121

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

编辑:添加代码示例:

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

6
在不是简单ANSI文本文件的任何文件(或任何具有编码前同步码的文件)上执行此操作时,请务必小心。请参阅下面的详细信息。
伊蒙2015年

您忘记了using子句/ IDisposable模式。.NET 4.0的新功能是StreamReader(stream,Encoding.UTF8,true,1024,true)和新的StreamWriter(stream,Encoding.UTF8,1024,true)克服了损坏的IDisposable模式(关闭StreamReader / Writer关闭基础流...甚至M $也不总是总是正确,至少在一开始)。如果您需要从一个流中读取多次,则可以有两个或多个StreamReader,每个都有自己的using子句(彼此之间不嵌套)。对于StreamWriter同样如此。每个文档都很少调用DiscardBufferedData。
TamusJRoyce,2016年

47

我使用这种方法:

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

24

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

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


18

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

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


1
如何将流复制到内存流?
knocte

OH我需要将响应设置回0,然后重新启动,但是如何?
PKCS12

1
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;
   }
}

5
请提供一些信息,说明为什么此代码片段可以解决问题中所述的问题。
Stephen Reindl

0

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

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());
}

这对我来说效果不佳。读取的HTML文件在读取第一行之后显示两次,然后使用建议的重置。也许它在某些情况下有效,但不适用于我的情况。
JohnH

1
如果我使用sr.BaseStream.Position = 0,效果很好;sr.DiscardBufferedData();
Chashitsu

0
public static void removeDuplicatedLinesBigFile2(string inFile, string outFile)
{
    int counter1 = 0, counter2 = 0;
    string line1, line2;
    bool band = false;

    // Read the file and display it line by line.  
    System.IO.StreamReader fileIN1 = new System.IO.StreamReader(inFile);
    System.IO.StreamReader fileIN2 = new System.IO.StreamReader(inFile);
    System.IO.StreamWriter fileOut = new System.IO.StreamWriter(outFile);

    while ((line1 = fileIN1.ReadLine()) != null)
    {
        //band = false;
        int counter = 0;
        fileIN2.BaseStream.Position = 0;
        fileIN2.DiscardBufferedData();

        while ((line2 = fileIN2.ReadLine()) != null)
        {                   
            if (line1.Equals(line2))
                counter++;

            if (counter > 1)
                break;
        }

        fileOut.WriteLine(line1);
        counter1++;
    }

    fileIN1.Close();
    fileIN2.Close();
    Console.WriteLine("Total Text Rows Copied: {0}", counter1);
}

此方法使您可以处理文本文件以创建一个新文件,并使您可以无效地复制重复的文本行。这是在BaseStream.Position = 0之后使用DiscardBufferedData()的示例;
莫里西奥·肯尼
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.