私の根本的な問題は、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;
}
.NET Framework 4.5以降を使用している場合は、 StreamWriterオーバーロードを使用して、ライターを閉じたときにベースストリームを開いたままにしておくことができます があります。
4.5より前の.NET Frameworkの以前のバージョンでは、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メソッドをオーバーライドする必要があります。disposingパラメーターに常にfalseを渡すことにより、ストリームライターを強制的に閉じず、StreamWriterはcloseメソッドでdisposeを呼び出すだけなので、必要はありません。それをオーバーライドします(もちろん、必要に応じてすべてのコンストラクターを追加できます。1つだけです)。
public class NoCloseStreamWriter : StreamWriter
{
public NoCloseStreamWriter(Stream stream, Encoding encoding)
: base(stream, encoding)
{
}
protected override void Dispose(bool disposing)
{
base.Dispose(false);
}
}