Есть ли способ закрыть StreamWriter без закрытия BaseStream?
Моя проблема с корнем заключается в том, что когда using
вызывает Dispose
на StreamWriter
, он также предоставляет BaseStream
(та же проблема с Close
).
У меня есть обходной путь для этого, но, как вы можете видеть, это связано с копированием потока. Есть ли способ сделать это без копирования потока?
Целью этого является получение содержимого строки (изначально прочитанной из базы данных) в поток, поэтому поток может быть прочитан сторонним компонентом.
NB: я не могу изменить сторонний компонент.
public System.IO.Stream CreateStream(string value)
{
var baseStream = new System.IO.MemoryStream();
var baseCopy = new System.IO.MemoryStream();
using (var writer = new System.IO.StreamWriter(baseStream, System.Text.Encoding.UTF8))
{
writer.Write(value);
writer.Flush();
baseStream.WriteTo(baseCopy);
}
baseCopy.Seek(0, System.IO.SeekOrigin.Begin);
return baseCopy;
}
Используется как
public void Noddy()
{
System.IO.Stream myStream = CreateStream("The contents of this string are unimportant");
My3rdPartyComponent.ReadFromStream(myStream);
}
В идеале я ищу мнимый метод под названием BreakAssociationWithBaseStream
, например.
public System.IO.Stream CreateStream_Alternate(string value)
{
var baseStream = new System.IO.MemoryStream();
using (var writer = new System.IO.StreamWriter(baseStream, System.Text.Encoding.UTF8))
{
writer.Write(value);
writer.Flush();
writer.BreakAssociationWithBaseStream();
}
return baseStream;
}
Ответы
Ответ 1
Если вы используете .NET Framework 4.5 или новее, существует перегрузка StreamWriter, с помощью которой вы можете попросить базовый поток оставаться открытым, когда автор закрытая.
В ранних версиях .NET Framework до 4.5, StreamWriter
предполагает, что он владеет потоком. Параметры:
- Не располагайте
StreamWriter
; просто промойте его.
- Создайте обертку потока, которая игнорирует вызовы
Close
/Dispose
, но проксирует все остальное. У меня есть реализация этого в MiscUtil, если вы хотите его оттуда оттуда.
Ответ 2
.NET 4.5 получил новый метод для этого!
http://msdn.microsoft.com/EN-US/library/gg712853(v=VS.110,d=hv.2).aspx
public StreamWriter(
Stream stream,
Encoding encoding,
int bufferSize,
bool leaveOpen
)
Ответ 3
Просто не назовите Dispose
на StreamWriter
. Причина, по которой этот класс является одноразовым, заключается не только в том, что он содержит неуправляемый ресурс, но и позволяет избавиться от потока, который сам может содержать неуправляемые ресурсы. Если жизнь основного потока обрабатывается в другом месте, не нужно распоряжаться писателем.
Ответ 4
Поток памяти имеет свойство ToArray, которое можно использовать даже при закрытии потока.
В Array записывается содержимое потока в массив байтов, независимо от свойства Position.
Вы можете создать новый поток на основе потока, который вы написали.
public System.IO.Stream CreateStream(string value)
{
var baseStream = new System.IO.MemoryStream();
var baseCopy = new System.IO.MemoryStream();
using (var writer = new System.IO.StreamWriter(baseStream, System.Text.Encoding.UTF8))
{
writer.Write(value);
writer.Flush();
baseStream.WriteTo(baseCopy);
}
var returnStream = new System.IO.MemoryStream( baseCopy.ToArray());
return returnStream;
}
Ответ 5
Вам необходимо создать потомок StreamWriter и переопределить его метод dispose, всегда передавая false параметру утилизации, он заставит автору потока НЕ закрываться, StreamWriter просто вызывает dispose в методе close, так что есть не нужно переопределять его (конечно, вы можете добавить все конструкторы, если хотите, у меня есть только один):
public class NoCloseStreamWriter : StreamWriter
{
public NoCloseStreamWriter(Stream stream, Encoding encoding)
: base(stream, encoding)
{
}
protected override void Dispose(bool disposing)
{
base.Dispose(false);
}
}