web-dev-qa-db-fra.com

convertir la chaîne en flux mémoire - Le flux mémoire n'est pas extensible?

j'essayais d'écrire une chaîne dans un flux de mémoire, mais j'ai échoué avec le message d'erreur:

Memory stream is not expandable.

la ligne de code qui produit ce problème:

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

quelqu'un a une solution de contournement/correctif pour cela?

trace de la pile:

[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

Un flux personnalisé qui ajoute les données serait plus approprié.

Peu testé. Suppose que vous souhaitez que le texte soit écrit lorsque le flux est vidé, puis une seule fois.

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

Le code suivant fonctionne correctement pour moi

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

Il semble que la bonne façon de procéder consiste à créer le MemoryStream à l'aide du constructeur par défaut

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

puis y écrire

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

si vous voulez pouvoir lire le flux normalement (par exemple en utilisant un StreamReader), vous devrez également appeler:

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

Lorsque vous créez un MemoryStream à partir d'un tableau d'octets, vous créez essentiellement un wrapper autour dudit tableau. Ce qui signifie que le tampon du flux ne peut pas s'étendre une fois qu'il a atteint sa capacité.

Cependant, un HttpResponse.Filter est essentiellement cela: a filtre. La documentation indique:

Lorsque vous créez un objet Stream et définissez la propriété Filter sur l'objet Stream, toutes les sorties HTTP envoyées par Write transitent par le filtre.

Les données finissent donc par être écrites dans le MemoryStream. Il serait donc utile de savoir exactement ce que vous essayez d'obtenir avec cela, car un MemoryStream ne ferait pas un filtre utile ...

3
Etienne de Martel
            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