Закрывает ли поток поток?
-
21-08-2019 - |
Вопрос
Я отправляю поток методам для записи, и в этих методах я использую двоичный модуль чтения/записи.Когда читатель/писатель избавляется, либо using
или просто когда на него нет ссылки, поток тоже закрывается??
Я бы отправил BinaryReader/Writer, но я тоже использую StreamReader (возможно, мне следует обойти это.Я использую это только для GetLine и ReadLine).Это довольно проблематично, если поток закрывается каждый раз, когда закрывается писатель/читатель.
Решение
Да, 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 (поток):
Этот конструктор инициализирует кодирование в UTF8Coding, свойство Beadestream с использованием параметра потока и размер внутреннего буфера до 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 закрывает соединение при его удалении.Однако «использование (Streamstream = ...){...}» с StreamReader/StreamWriter может привести к тому, что поток будет удален дважды:(1) когда объект StreamReader удаляется (2) и когда блок Stream using закрывается.Это приводит к появлению предупреждения CA2202 при запуске анализа кода VS.
Другое решение, взятое непосредственно из CA2202 page, заключается в использовании блока 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() и IDisposable (что и делает «использование») должен заставить объект очистить все свои ресурсы.Это включает в себя очистку потоков и закрытие их файловых дескрипторов.
Если в вашем случае вы хотите передать его другим методам, вам необходимо убедиться, что эти методы не выполняют чтение/запись в блоке использования.
Если вам нужно, простой способ исправить это — переопределить метод Dispose классов StreamWriter.Смотрите мой пост здесь, чтобы узнать, как это сделать:
поток удаляется либо с помощью ключевого слова «using», либо путем явного вызова