2012-09-09 10 views
7

Estoy tratando de agregar algunos datos a una transmisión. Esto funciona bien con FileStream, pero no para MemoryStream debido al tamaño de búfer fijo.Anexando a MemoryStream

El método que escribe datos en la secuencia está separado del método que crea la secuencia (lo he simplificado enormemente en el siguiente ejemplo). El método que crea la secuencia no tiene conocimiento de la longitud de los datos que se escribirán en la secuencia.

public void Foo(){ 
    byte[] existingData = System.Text.Encoding.UTF8.GetBytes("foo"); 
    Stream s1 = new FileStream("someFile.txt", FileMode.Append, FileAccess.Write, FileShare.Read); 
    s1.Write(existingData, 0, existingData.Length); 


    Stream s2 = new MemoryStream(existingData, 0, existingData.Length, true); 
    s2.Seek(0, SeekOrigin.End); //move to end of the stream for appending 

    WriteUnknownDataToStream(s1); 
    WriteUnknownDataToStream(s2); // NotSupportedException is thrown as the MemoryStream is not expandable 
} 

public static void WriteUnknownDataToStream(Stream s) 
{ 
    // this is some example data for this SO query - the real data is generated elsewhere and is of a variable, and often large, size. 
    byte[] newBytesToWrite = System.Text.Encoding.UTF8.GetBytes("bar"); // the length of this is not known before the stream is created. 
    s.Write(newBytesToWrite, 0, newBytesToWrite.Length); 
} 

Una idea que tenía era enviar un ampliable MemoryStream a la función, tiene que poner los datos devueltos a los datos existentes.

public void ModifiedFoo() 
{ 
    byte[] existingData = System.Text.Encoding.UTF8.GetBytes("foo"); 
    Stream s2 = new MemoryStream(); // expandable capacity memory stream 

    WriteUnknownDataToStream(s2); 

    // append the data which has been written into s2 to the existingData 
    byte[] buffer = new byte[existingData.Length + s2.Length]; 
    Buffer.BlockCopy(existingData, 0, buffer, 0, existingData.Length); 
    Stream merger = new MemoryStream(buffer, true); 
    merger.Seek(existingData.Length, SeekOrigin.Begin); 
    s2.CopyTo(merger); 
} 

¿Alguna solución mejor (más eficiente)?

+3

¿Puede explicar por qué no está utilizando una secuencia expandible para ambas escrituras? – Rotem

+1

ah, como tal? Stream s2 = new MemoryStream(); // secuencia de memoria de capacidad expandible s2.Write (existingData, 0, existingData.Length); WriteUnknownDataToStream (s2); –

+0

Sí, eso es lo que quiero decir ... es por eso que es una transmisión y no una matriz, ¿no? – Rotem

Respuesta

25

Una posible solución no es limitar la capacidad del MemoryStream en primer lugar. Si no sabe de antemano el número total de bytes que necesitará escribir, cree un MemoryStream con una capacidad no especificada y utilícelo para ambas escrituras.

byte[] existingData = System.Text.Encoding.UTF8.GetBytes("foo"); 
MemoryStream ms = new MemoryStream(); 
ms.Write(existingData, 0, existingData.Length); 
WriteUnknownData(ms); 

Esto, sin duda, ser menos eficiente que la inicialización de un MemoryStream de un byte[], pero si usted necesita para continuar escribiendo a la corriente creo que es su única opción.

+1

Si la diferencia de rendimiento es importante, puede [especificar la capacidad inicial de la transmisión] (http://msdn.microsoft.com/en-us/library/bx3c0489.aspx). De esta forma, si adivinas bien (o conoces) el tamaño final, no habrá reasignaciones. Si adivina mal, desperdiciará la memoria o tendrá reasignaciones que afectan el rendimiento, pero aún así funcionará. – svick