web-dev-qa-db-ja.com

BaseStreamを閉じずにStreamWriterを閉じる方法はありますか?

私の根本的な問題は、usingDisposeStreamWriterを呼び出すと、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;
}
104
Binary Worrier

.NET Framework 4.5以降を使用している場合は、 StreamWriterオーバーロードを使用して、ライターを閉じたときにベースストリームを開いたままにしておくことができます があります。

4.5より前の.NET Frameworkの以前のバージョンでは、StreamWriterはストリームを所有していると想定します。オプション:

  • StreamWriter;を処分しないでください。フラッシュするだけです。
  • Close/Disposeへの呼び出しを無視するが、他のすべてをプロキシするストリームラッパーを作成します。そこから取得したい場合は、 MiscUtil で実装しています。
106
Jon Skeet

.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
)
41
maliger

DisposeStreamWriterを呼び出さないでください。このクラスが使い捨てである理由は、管理されていないリソースを保持しているためではなく、それ自体が管理されていないリソースを保持できるストリームの廃棄を許可するためです。基になるストリームの寿命が他の場所で処理される場合、ライターを破棄する必要はありません。

32
Darin Dimitrov

メモリストリームには、ストリームが閉じている場合でも使用できる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;
}
5
Tudor

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);
    }
}
1