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

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

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

7 ответов

Решение

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

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

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

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

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

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

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

Со страницы msdn для Конструктора StreamReader (Stream):

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

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

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

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

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

Да, это так. Вы можете убедиться в этом, посмотрев реализацию с помощью 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);
        }
    }
}

Шесть лет спустя, но, может быть, это кому-нибудь поможет.

StreamReader закрывает соединение, когда оно удаляется. Однако "использование (Stream stream = ...){...}" с StreamReader/StreamWriter может привести к тому, что поток будет удален дважды: (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...
}

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

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

Простой способ исправить это, если вам нужно, это переопределить метод Dispose классов StreamWriter. Смотрите мой пост здесь для кода о том, как это сделать:

. Удаляет ли StreamWriter базовый поток?

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

Другие вопросы по тегам