Утилизирует ли поток 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" ) должен сделать объект очисткой всех его ресурсов. Это включает потоки, смывающие и закрывающие их файловые дескрипторы.
Если в вашем случае вы хотите передать его другим методам, вам необходимо убедиться, что эти методы не выполняют чтение/запись в используемом блоке.
Ответ 6
Легкий способ исправить это, если вам нужно переопределить классы StreamWriter Dispose. См. Мой пост здесь для кода о том, как это сделать:
Does. Развертывание StreamWriter для закрытого потока?
Ответ 7
поток, расположенный либо с помощью ключевого слова "using", либо явно вызывая dispose