2011-04-13 73 views
23

No estoy seguro de lo que estoy haciendo mal, he visto muchos ejemplos, pero parece que no funciona.Escribir en MemoryStream con StreamWriter devuelve vacío

public static Stream Foo() 
{ 
    var memStream = new MemoryStream(); 
    var streamWriter = new StreamWriter(memStream); 

    for (int i = 0; i < 6; i++) 
     streamWriter.WriteLine("TEST"); 

    memStream.Seek(0, SeekOrigin.Begin); 
    return memStream; 
} 

que estoy haciendo una prueba sencilla de este método para tratar de conseguir que pase, pero no importa qué, mi conteo colección es 0.

[Test] 
public void TestStreamRowCount() 
{ 
    var stream = Foo(); 

    using (var reader = new StreamReader(stream)) 
    { 
     var collection = new List<string>(); 
     string input; 

     while ((input = reader.ReadLine()) != null) 
      collection.Add(input); 

     Assert.AreEqual(6, collection.Count); 
    } 
} 

Nota: He cambiado alguna sintaxis anterior sin compilando en el método de prueba. Lo que es más importante es el primer método que parece devolver una secuencia vacía (mi reader.ReadLine() siempre lee una vez). No estoy seguro de lo que estoy haciendo mal. Gracias.

Respuesta

49

Olvidándose de enjuagar su instancia de StreamWriter.

public static Stream Foo() 
{ 
    var memStream = new MemoryStream(); 
    var streamWriter = new StreamWriter(memStream); 

    for (int i = 0; i < 6; i++) 
     streamWriter.WriteLine("TEST"); 

    streamWriter.Flush();         <-- need this 
    memStream.Seek(0, SeekOrigin.Begin); 
    return memStream; 
} 

También tenga en cuenta que StreamWriter se supone que ser eliminados, ya que implementa IDisposable, pero que a su vez genera otro problema, que cerrará el MemoryStream subyacente, así.

¿Estás seguro de que deseas devolver MemoryStream aquí?

me gustaría cambiar el código para esto:

public static byte[] Foo() 
{ 
    using (var memStream = new MemoryStream()) 
    using (var streamWriter = new StreamWriter(memStream)) 
    { 
     for (int i = 0; i < 6; i++) 
      streamWriter.WriteLine("TEST"); 

     streamWriter.Flush(); 
     return memStream.ToArray(); 
    } 
} 

[Test] 
public void TestStreamRowCount() 
{ 
    var bytes = Foo(); 

    using (var stream = new MemoryStream(bytes)) 
    using (var reader = new StreamReader(stream)) 
    { 
     var collection = new List<string>(); 
     string input; 

     while ((input = reader.ReadLine()) != null) 
      collection.Add(input); 

     Assert.AreEqual(6, collection.Count); 
    } 
} 
+3

que no están de acuerdo con su conversión en una matriz. Un MemoryStream puede actuar como un simple flujo de Stream y la mayoría de las veces al consumidor no le importa su implementación. Muchas veces utiliza un MemoryStream mientras prueba y un flujo de archivos durante la producción, por ejemplo –

+1

Para mis propósitos, sí quiero devolver un Stream. Por la misma razón Matt mencionó anteriormente. Flushing the StreamWriter era lo que me estaba perdiendo. Gracias. – jsmith

+0

Sé que esta es una publicación antigua. Pero simplemente me salvó. Gracias :) – Andrew

4

Trate lavado StreamWriter después de escribir sus líneas.

+1

Flushing the stream me ayudó! Solo una nota al margen; Estaba escribiendo 1348 bytes en la secuencia de memoria utilizando el escritor de secuencias. Escribiría 1024 bytes (sin enrojecimiento) y tardé años en descifrarlo, pero al final el enjuague movió los otros 324 bytes. – Dave

11

Como no está utilizando "using" o streamWriter.Flush() el escritor no ha confirmado cambios en la transmisión. Como resultado Stream itslef aún no tiene datos. En general, usted desea ajustar la manipulación con las instancias Stream y StremaWriter con el uso.

También debe considerar volver nueva instancia de MemoryStream:

using(var memStream = new MemoryStream()) 
{ 
    .... 
    return new MemoryStream(memStream.ToArray(), false /*writable*/); 
} 
+0

¿Por qué quieres devolver una nueva instancia de MemoryStream? ¿No sería esto ineficiente y redundante? – jsmith

+4

Para que sea de solo lectura, para dejar de usar memoria adicional asignada para la secuencia de escritura, para permitir el patrón de código de secuencia normal con "usar" alrededor de la creación de la secuencia. En este caso particular, no es muy importante, pero a menudo es agradable devolver la transmisión que la persona que llama puede usar de la forma que quiera sin preocuparse si la transmisión de flujo continuo se cierra o cambia. En este caso particular, puede crear una nueva secuencia de manera muy eficiente mediante el uso de GetBuffer en lugar de ToArray (que hace una copia del buffer interno). –

Cuestiones relacionadas