web-dev-qa-db-ja.com

文字列をメモリストリームに変換する-メモリストリームは拡張できませんか?

文字列をメモリストリームに書き込もうとしていましたが、エラーメッセージで失敗しました。

Memory stream is not expandable.

この問題を引き起こすコード行:

context.Response.Filter = new System.IO.MemoryStream(System.Text.Encoding.UTF8.GetBytes(myPage));

誰かがそのための回避策/修正を持っていますか?

スタックトレース:

[NotSupportedException: Memory stream is not expandable.]
   System.IO.MemoryStream.set_Capacity(Int32 value) +9385744
   System.IO.MemoryStream.EnsureCapacity(Int32 value) +50
   System.IO.MemoryStream.Write(Byte[] buffer, Int32 offset, Int32 count) +265
   System.Web.HttpWriter.FilterIntegrated(Boolean finalFiltering, IIS7WorkerRequest wr) +9155697
   System.Web.HttpResponse.FilterOutput() +159
   System.Web.CallFilterExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +52
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +75
35
Dementic

データを追加するカスタムストリームの方が適切です。

最小限のテスト。ストリームがフラッシュされたときに、テキストを1回だけ書き込むと仮定します。

public class AppendTextFilter : Stream
{
    private Stream Filter { get; set; }
    private string Text { get; set; }
    private bool TextWritten { get; set; }

    public AppendTextFilter( Stream filter, string text )
    {
        this.Filter = filter;
        this.Text = text;
    }

    public override bool CanRead { get { return Filter.CanRead; } }

    public override bool CanSeek { get { return Filter.CanSeek; } }

    public override bool CanWrite { get { return Filter.CanWrite; } }

    public override void Flush()
    {
        if (!TextWritten)
        {
            var bytes = Encoding.UTF7.GetBytes( Text );
            Filter.Write( bytes, 0, bytes.Length );
            TextWritten = true;
        }
        Filter.Flush();
    }

    public override long Length { get { return Filter.Length + Text.Length; } }

    public override long Position
    {
        get
        {
            return Filter.Position;
        }
        set
        {
            Filter.Position = value;
        }
    }

    public override int Read( byte[] buffer, int offset, int count )
    {
        return Filter.Read( buffer, offset, count );
    }

    public override long Seek( long offset, SeekOrigin Origin )
    {
        return Filter.Seek( offset, Origin );
    }

    public override void SetLength( long value )
    {
        Filter.SetLength( value );
    }

    public override void Write( byte[] buffer, int offset, int count )
    {
        Filter.Write( buffer, offset, count );
    }
}
4
tvanfosson

次のコードは私のために正しく動作します

public class Foo
{
    public static void Main()
    {
        var myPage = "test string";
        var repo =  new System.IO.MemoryStream(System.Text.Encoding.UTF8.GetBytes(myPage));
    }
}

これを行う正しい方法は、デフォルトのコンストラクタを使用してMemoryStreamを作成することです

var repo = new System.IO.MemoryStream();

そして、それに書き込みます

var stringBytes = System.Text.Encoding.UTF8.GetBytes(myPage);
repo.Write(stringBytes, 0, stringBytes.Length);

ストリームを通常の方法で(たとえば、StreamReaderを使用して)読み取ることができるようにしたい場合は、以下も呼び出す必要があります。

repo.Seek(0, SeekOrigin.Begin);
79
msarchet

バイト配列からMemoryStreamを作成するとき、基本的にはその配列の周りにラッパーを作成します。つまり、ストリームのバッファは容量に達すると拡張できません。

ただし、HttpResponse.Filterは基本的に次のとおりです。afilter。ドキュメントの状態:

Streamオブジェクトを作成し、FilterプロパティをStreamオブジェクトに設定すると、Writeによって送信されたすべてのHTTP出力がフィルターを通過します。

したがって、データはMemoryStreamに書き込まれます。 MemoryStreamは有用なフィルターを作成しないので、これで何を達成しようとしているのかを正確に知るのに役立ちます...

3
            byte[] buffer = File.ReadAllBytes("test.xml");
            XmlDocument doc = new XmlDocument();
            using (MemoryStream output = new MemoryStream())
            {
                using (MemoryStream ms = new MemoryStream(buffer ))
                {
                    doc.Load(ms);
                }
                // Make changes to your memory stream here
                doc.Save(output);//Output stream has the changes.
            }
2
sowmzs