在处理基础流之后使用StreamReader?

时间:2011-09-12 18:13:44

标签: c# stream idisposable

使用StreamReader,如果你处理了底层流,我认为你应该再也不能阅读了。

这是真的建议this问题,如果底层流的生命在其他地方处理的话,建议您不必处置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

这怎么可能?

3 个答案:

答案 0 :(得分:10)

您的StreamReader已经将下一行读入其缓冲区 在缓冲区中的数据耗尽之前,它不会返回源Stream

事实上,在这种情况下它不可能抛出异常,因为没有幂等方法来确定是否已经处置了Stream。 (没有IsDisposed属性)

答案 1 :(得分:5)

要添加到@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行。

答案 2 :(得分:0)

您需要了解的是dispose正在尝试做什么。

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

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