StreamReader.ReadLine 将无限循环

本文关键字:无限循环 ReadLine StreamReader | 更新日期: 2023-09-27 18:33:59

我有一个简单的程序来读取文件并使用StreamReader逐行处理它。但是我正在读取的文件有时可能位于网络文件夹中。我在对这样一个文件进行一些测试时遇到了这种情况,如果在我阅读时的某个时候网络连接丢失,它将一次又一次地保持在同一行中,通过产生与流结果相同的行,在无限循环中循环。ReadLine()。

当流本身无法使用 fileHandle 时,有没有办法找到?我预计当文件句柄从流阅读器丢失时,会触发FileNotAvailableException类型的异常。

这是我的代码片段...

        string file = @"Z://1601120903.csv"; //Network file
        string line;
        StringBuilder stb = new StringBuilder();      
        StreamReader stream = new StreamReader(file, Encoding.UTF8, true, 1048576);
        do
        {
            line = stream.ReadLine();
            // Do some work here
        } while (line != "");

StreamReader.ReadLine 将无限循环

null 不与空字符串进行比较:

https://msdn.microsoft.com/en-us/library/system.io.streamreader.readline(v=vs.110).aspx

返回值类型:系统字符串 输入流中的下一行, 如果到达输入流的末尾,则为 null。

    do
    {
        line = stream.ReadLine();
        // Do some work here
    } while (line != null);

但是,更好的方法是让 .Net 为您完成工作(逐行文件读取)并删除所有读取器:

  foreach (String line in File.ReadLines(file)) {
    // Do some work here
  }

正确的方法 1 (EndOfStream) :

using(StreamReader sr = new StreamReader(...)) {
    while(!sr.EndOfStream) {
        string line = sr.ReadLine();
        Console.WriteLine(line);
    }
}

正确的方法 2(速览)

using(StreamReader sr = new StreamReader(...)) {
    while(sr.Peek() >= 0) {
        string line = sr.ReadLine();
    }
}

注意:威胁空字符串作为文件末尾是不正确的。

如果在我阅读时的某个时候网络连接丢失, 它会一次又一次地保持在同一条线上,在无限中循环 通过生成与流中的结果相同的行进行循环。ReadLine()

我现在检查了这种情况 - 在这种情况下应该抛出System.IO.IOException("找不到网络路径"}。

用 try catch 块包装它不会解决我的问题,对吗?

在这种情况下,您可以按如下方式中断读数:

string line;
do {
    try {
        line = sr.ReadLine();
        // Do some work here
    }
    catch(System.IO.IOException) {
        break; 
    }
} while(line != null);

如果你用while -loop编写它:

while ((line = sr.ReadLine()) != null)
{
    Console.WriteLine(line);
}

另一种方法是使用 File.ReadAllLines(),它将负责打开文件并读取所有行并关闭文件,还可以处理网络连接丢失的情况。

var lines = File.ReadAllLines("Z://1601120903.csv");
foreach(line in lines)
{
 // Do some work
}

假设文件在读取时不应该更改并且它不是很大,您可能需要考虑将其复制到临时文件(本地),然后在不受干扰的情况下对其进行处理。

如果您想获取您到达的地方的索引,这可能会有所帮助:如何知道流阅读器在文本文件中的位置(行号)?

如果您的流是 NetworkStream,则 ReadLine 方法将无限期地期望来自流的更多内容(如果它到达末尾)。我认为,根据 StreamReader 文档,它旨在仅适用于本地文件流。在这种情况下,您可以直接从网络流读取字节。

https://learn.microsoft.com/pt-br/dotnet/api/system.net.sockets.networkstream.read?view=netcore-3.1#System_Net_Sockets_NetworkStream_Read_System_Span_System_Byte__