在底层流被处理后使用StreamReader

本文关键字:StreamReader 处理 在底层 | 更新日期: 2023-09-27 18:08:16

使用StreamReader,如果您处置底层流,我认为您不应该能够再读取。

这是真的,这就提出了这个问题,如果底层流的生命周期在其他地方处理,则建议您不必处置StreamWriter(在它们的情况下)。

但事实并非如此。我所做的是:

我有一个名为delme.txt的文件,其中包含以下

abc
def
ghi

我运行这个:

    Stream s = File.OpenRead(@"C:'delme.txt");
    StreamReader sr = new StreamReader(s, Encoding.ASCII);
    Console.WriteLine(sr.ReadLine());
    s.Dispose();
    Console.WriteLine(sr.ReadLine());

结果是:

abc
def

这怎么可能?

在底层流被处理后使用StreamReader

您的StreamReader已经将下一行读入其缓冲区。
它不会回到源Stream,直到它的缓冲区中的数据用完。

实际上,在这种情况下,它不可能抛出异常,因为没有幂等的方法来发现Stream是否已被处置。(没有IsDisposed属性)

要添加@SLaks的答案,下面将演示(使用一个包含数千行文本的文件):

        Stream s = File.OpenRead(path);
        StreamReader sr = new StreamReader(s, Encoding.ASCII);
        Console.WriteLine(sr.ReadLine());
        s.Dispose();
        int i = 1;
        try
        {
            while (!sr.EndOfStream)
            {
                Console.WriteLine(sr.ReadLine());
                i++;
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        Console.WriteLine(i + " lines total");
        Console.ReadLine();

它会打印出很多很多行,比如几百行,然后抛出一个异常。我的输出是这样结束的:

qrs
tuv
wxy
zab
cde
fgh
ijk
lmn
Cannot access a closed file.
204 lines total

实际上,我们看到StreamReader有一个构造函数,它接受参数bufferSize作为第四个参数:

StreamReader sr = new StreamReader(s, Encoding.ASCII, false, 10000);

使用10000,在崩溃之前,它实际上为我打印了总共1248行。另外,您可以使用的最小值是1,在这种情况下,它仍然预取25行。

您需要了解的是dispose要做什么。

http://msdn.microsoft.com/en-us/library/ms227563.aspx

它说如果TextReader完成,TextReader将处于不可用状态。也许,因为它还没有读完所有的东西,所以它还没有被认为完成;因此,您可以继续使用它。这是我的猜测。