Есть ли способ закрыть 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;
}
5 ответов
Если вы используете.NET Framework 4.5 или более позднюю версию, существует перегрузка StreamWriter, с помощью которой вы можете попросить оставить основной поток открытым, когда устройство записи закрыто.
В более ранних версиях.NET Framework до 4.5, StreamWriter
Предполагается, что он владеет потоком. Опции:
- Не выбрасывайте
StreamWriter
; просто промой это. - Создать потоковую оболочку, которая игнорирует вызовы
Close
/Dispose
но прокси все остальное вместе. У меня есть реализация этого в MiscUtil, если вы хотите взять его оттуда.
.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
)
Просто не звони Dispose
на StreamWriter
, Причина, по которой этот класс является одноразовым, заключается не в том, что он содержит неуправляемые ресурсы, а в том, что он позволяет избавиться от потока, который сам может содержать неуправляемые ресурсы. Если жизнь базового потока обрабатывается в другом месте, нет необходимости распоряжаться писателем.
Поток памяти имеет свойство ToArray, которое можно использовать, даже когда поток закрыт. To 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;
}
Вам нужно создать потомка 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);
}
}