Утилизирует ли 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. Смотрите мой пост здесь для кода о том, как это сделать:
Поток удаляется либо с помощью ключевого слова "using", либо с помощью явного вызова dispose