Утилизирует ли поток streamreader поток потока?

Я посылаю поток методам для записи, и в этих методах я использую бинарный считыватель /wrtier. Когда читатель/писатель находится в распоряжении, либо с помощью using, либо просто, когда он не ссылается, поток также закрыт?

Я бы отправил BinaryReader/Writer, но я тоже использую StreamReader (возможно, мне стоит обойти это. Я использую это только для GetLine и ReadLine). Это довольно хлопотно, если он закрывает поток каждый раз, когда писатель/читатель закрывается.

Ответ 1

Да, StreamReader, StreamWriter, BinaryReader и BinaryWriter все закрывают/удаляют свои базовые потоки, когда вы вызываете Dispose на них. Они не распоряжаются потоком, если читатель/писатель - это просто мусор, собранный, хотя вы всегда должны распоряжаться читателем/писателем, предпочтительно с помощью инструкции using. (На самом деле, ни один из этих классов не имеет финализаторов, и они не должны иметь.)

Лично я предпочитаю использовать инструкцию для потока. Вы можете довольно быстро вложить выражения using без фигурных скобок:

using (Stream stream = ...)
using (StreamReader reader = new StreamReader(stream, Encoding.Whatever))
{
}

Несмотря на то, что оператор using для потока несколько избыточен (если конструктор StreamReader не генерирует исключение), я считаю, что лучше всего использовать, если вы избавитесь от StreamReader и просто используете поток непосредственно в более поздняя дата, вы уже имеете правильную семантику выбора.

Ответ 2

Это старый, но я хотел сегодня сделать что-то похожее и обнаружил, что все изменилось. Начиная с .net 4.5, существует аргумент leaveOpen:

public StreamReader( Stream stream, Encoding encoding, bool detectEncodingFromByteOrderMarks, int bufferSize, bool leaveOpen )

Единственная проблема заключается в том, что не совсем очевидно, что задать для других параметров. Вот вам помощь:

От страницы msdn для StreamReader Constructor (Stream):

Этот конструктор инициализирует кодировку UTF8Encoding, Свойство BaseStream с использованием параметра потока и внутреннего размер буфера до 1024 байта.

Это просто оставляет detectEncodingFromByteOrderMarks, который, судя по исходному коду, true

public StreamReader(Stream stream)
        : this(stream, true) {
}

public StreamReader(Stream stream, bool detectEncodingFromByteOrderMarks)
        : this(stream, Encoding.UTF8, detectEncodingFromByteOrderMarks, DefaultBufferSize) {
}

Было бы неплохо, если бы некоторые из этих значений по умолчанию были выставлены или аргументы были необязательными, чтобы мы могли просто указать те, которые мы хотим.

Ответ 3

Да, да. Вы можете проверить это, посмотрев на реализацию с помощью Reflector.

protected override void Dispose(bool disposing)
{
    try
    {
        if ((this.Closable && disposing) && (this.stream != null))
        {
            this.stream.Close();
        }
    }
    finally
    {
        if (this.Closable && (this.stream != null))
        {    
            this.stream = null;    
            this.encoding = null;
            this.decoder = null;
            this.byteBuffer = null;
            this.charBuffer = null;
            this.charPos = 0;
            this.charLen = 0;
            base.Dispose(disposing);
        }
    }
}

Ответ 4

Шесть лет спустя, но, возможно, это может помочь кому-то.

StreamReader закрывает соединение при его удалении. Однако "использование (Stream stream =...) {...}" с StreamReader/StreamWriter может привести к тому, что Stream будет удален дважды: (1) когда объект StreamReader расположен (2) и когда блок с использованием потока закрывается. Это приводит к предупреждению CA2202 при анализе кода VS.

Другим решением, взятым непосредственно с CA2202, является использование блока try/finally. Правильно настройте, это только закроет соединение один раз.

В нижней части CA2202 корпорация Microsoft рекомендует использовать следующее:

Stream stream = null;
try
{
    stream = new FileStream("file.txt", FileMode.OpenOrCreate);
    using (StreamWriter writer = new StreamWriter(stream))
    {
        stream = null;
        // Use the writer object...
    }
}
finally
{
    if(stream != null)
        stream.Dispose();
}

вместо...

// Generates a CA2202 warning
using (Stream stream = new FileStream("file.txt", FileMode.Open))
using (XmlReader reader = new XmlReader (stream))
{
    // Use the reader object...
}

Ответ 5

Да. Вызов Dispose() on и IDisposable (который использует "using" ) должен сделать объект очисткой всех его ресурсов. Это включает потоки, смывающие и закрывающие их файловые дескрипторы.

Если в вашем случае вы хотите передать его другим методам, вам необходимо убедиться, что эти методы не выполняют чтение/запись в используемом блоке.

Ответ 7

поток, расположенный либо с помощью ключевого слова "using", либо явно вызывая dispose