преобразовать строку в поток памяти - поток памяти не расширяется?

я пытался записать строку в поток памяти, но не смог с сообщением об ошибке:

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

person Rafael Herscovici    schedule 11.11.2011    source источник
comment
что такое `mypage' строка напрямую?   -  person msarchet    schedule 11.11.2011
comment
Что ты пытаешься сделать? Из того, что я получил в документации, HttpResponse.Filter не предназначен для такого использования.   -  person Etienne de Martel    schedule 11.11.2011
comment
@msarchet = да, это строка.   -  person Rafael Herscovici    schedule 11.11.2011
comment
@EtiennedeMartel - если вы попытаетесь манипулировать ответом, это правильный путь. msdn.microsoft.com/en-us/library/   -  person Rafael Herscovici    schedule 11.11.2011
comment
Да, но если вы хотите что-то вывести в ответ, почему бы просто не вызвать Write? Что вы пытаетесь сделать здесь?   -  person Etienne de Martel    schedule 11.11.2011
comment
это внутри httpmodule... я не хочу писать ответ, опять же, я манипулирую ответом.   -  person Rafael Herscovici    schedule 11.11.2011
comment
Что ж, если он находится внутри HttpModule, у вас есть полный контроль над фактическим выходом HTTP. Поэтому должно быть легко написать то, что вы хотите.   -  person Etienne de Martel    schedule 11.11.2011
comment
Вероятно, вам следует использовать собственный поток, который принимает текущий фильтр в качестве параметра и добавляет к нему.   -  person tvanfosson    schedule 11.11.2011
comment
@tvanfosson, я думаю, ты прав, есть какой-нибудь пример для этого?   -  person Rafael Herscovici    schedule 11.11.2011
comment
Пожалуйста, примите самый полезный ответ ниже   -  person andruso    schedule 15.01.2021


Ответы (3)


Следующий код работает правильно для меня

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);
person msarchet    schedule 11.11.2011

Пользовательский поток, который добавляет данные, был бы более подходящим.

Минимально проверено. Предполагается, что вы хотите, чтобы текст записывался при сбросе потока, а затем только один раз.

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 );
    }
}
person tvanfosson    schedule 11.11.2011

Когда вы создаете MemoryStream из массива байтов, вы, по сути, создаете оболочку вокруг указанного массива. Это означает, что буфер потока не может расширяться, как только он достигает своей емкости.

Однако HttpResponse.Filter по существу является фильтром. В документации указано:

Когда вы создаете объект Stream и задаете свойство Filter для объекта Stream, все выходные данные HTTP, отправленные Write, проходят через фильтр.

Таким образом, данные в конечном итоге записываются в файл MemoryStream. Так что было бы полезно знать, чего именно вы пытаетесь достичь с помощью этого, потому что MemoryStream не будет полезным фильтром...

person Etienne de Martel    schedule 11.11.2011
comment
я пытаюсь манипулировать ответом, добавил текст на страницу. это оно. - person Rafael Herscovici; 11.11.2011