【问题标题】:Return StreamReader to Beginning将 StreamReader 返回到开头
【发布时间】:2011-01-04 10:09:18
【问题描述】:

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

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

我有一个聪明的主意,使用FileStream.Seek(long, SeekOffset) 在文件中移动,但封闭的System.IO.StreamReader 没有效果。我可以Close() 并重新分配流和阅读器引用,但我希望有更好的方法。

【问题讨论】:

    标签: c# .net


    【解决方案1】:

    您需要像您一样在流中搜索,然后在StreamReader 上调用DiscardBufferedData。文档here:

    编辑:添加代码示例:

    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
    

    【讨论】:

    • 在任何不是简单 ANSI 文本文件(或者更确切地说是任何具有编码前导码的文件)的文件上执行此操作时要小心。有关更多详细信息,请参阅下面的答案。
    • 您忘记了 using 子句/IDisposable 模式。 .NET 4.0 的新功能是 StreamReader(stream, Encoding.UTF8, true, 1024, true) 和 new StreamWriter(stream, Encoding.UTF8, 1024, true) 克服了 IDisposable 模式的问题(关闭 StreamReader/Writer 会关闭底层流...即使是 M$ 也不总是正确的,至少一开始是这样)。如果您需要多次从流中读取数据,请拥有两个或多个 StreamReader,每个 StreamReader 在各自的 using 子句中(不相互嵌套)。 StreamWriter 也是如此。根据文档,您很少会调用 DiscardBufferedData。
    【解决方案2】:

    我用这个方法:

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

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        【解决方案4】:

        如果BaseStream 实际上可以将Position 属性设置为0,那就太好了。

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

        【讨论】:

        • 如何将流复制到内存流中?
        • 哦,我需要将响应设置回位置 0 并重新启动,但是如何?
        【解决方案5】:
        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;
           }
        }
        

        【讨论】:

        • 请提供一些信息为什么这个代码片段解决了问题中描述的问题。
        【解决方案6】:

        我创建了一个简单的方法,您可以使用它来重置 StreamReader。

        using (var reader = StreamReader(filePath))
        {
           reader.ReadLine();
           reader.ReadLine();
           ResetReader(reader);
        }
        
        
        private static void ResetReader(StreamReader reader)
        
         {
             reader.DiscardBufferedData();
             reader.BaseStream.Seek(0, SeekOrigin.Begin);
         }
        

        【讨论】:

          【解决方案7】:

          问题是寻找某种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 文件在读取第一行后显示了两次,然后使用了建议的重置。也许它适用于某些情况,但不适用于我。
          • 如果我使用 sr.BaseStream.Position = 0; 效果很好; sr.DiscardBufferedData();
          【解决方案8】:
          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() 的示例;
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2014-12-09
          • 2013-10-11
          • 2015-12-13
          • 2015-05-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多