2010-02-10 19 views
40

¿Cuál es el mejor método para escribir un StringBuilder en System.IO.Stream?Escribir StringBuilder en Stream

actualmente estoy haciendo:

StringBuilder message = new StringBuilder("All your base"); 
message.Append(" are belong to us"); 

System.IO.MemoryStream stream = new System.IO.MemoryStream(); 
System.Text.ASCIIEncoding encoding = new ASCIIEncoding(); 
stream.Write(encoder.GetBytes(message.ToString()), 0, message.Length); 

Respuesta

62

No utilice un StringBuilder, si usted está escribiendo a una corriente, no sólo que con un StreamWriter:

using (var memoryStream = new MemoryStream()) 
using (var writer = new StreamWriter(memoryStream)) 
{ 
    // Various for loops etc as necessary that will ultimately do this: 
    writer.Write(...); 
} 
+6

No es posible si necesita usar la cadena para otra cosa antes de escribirla. – Skurmedel

+10

Absolutamente cierto, pero por supuesto no ha dicho que sea un requisito, así que no hice ninguna suposición. –

12

Esa es la mejor método. Otras pérdidas sabia el StringBuilder y usar algo como lo siguiente:

using (MemoryStream ms = new MemoryStream()) 
{ 
    using (StreamWriter sw = new StreamWriter(ms, Encoding.Unicode)) 
    { 
     sw.WriteLine("dirty world."); 
    } 
    //do somthing with ms 
} 
4

Dependiendo de su caso de uso también puede tener sentido para empezar sólo con un StringWriter:

StringBuilder sb = null; 

// StringWriter - a TextWriter backed by a StringBuilder 
using (var writer = new StringWriter()) 
{ 
    writer.WriteLine("Blah"); 
    . . . 
    sb = writer.GetStringBuilder(); // Get the backing StringBuilder out 
} 

// Do whatever you want with the StringBuilder 
+1

Bastante seguro: https://msdn.microsoft.com/en-us/library/system.io.stringwriter.getstringbuilder(v=vs.110).aspx –

4

Tal vez sea útil.

var sb= new StringBuilder("All your money"); 
sb.Append(" are belong to us, dude."); 
var myString = sb.ToString(); 
var myByteArray = System.Text.Encoding.UTF8.GetBytes(myString); 
var ms = new MemoryStream(myByteArray); 
// Do what you need with MemoryStream 
+2

Copie primero en una cadena y luego vuelva a copiar en una matriz de bytes , luego finalmente copia a la secuencia? De Verdad? Seguramente esto se puede hacer de manera sucinta sin hacer ninguna copia intermedia. (¿Qué sucede si el generador de cadenas tiene 2 GB?) –

0

Si desea utilizar algo así como un StringBuilder porque es más limpio para pasar alrededor y trabajar con él, entonces se puede usar algo como el siguiente alternativo StringBuilder creé.

Lo más importante que hace diferente es que permite el acceso a los datos internos sin tener que ensamblar primero en un String o ByteArray. Esto significa que no tiene que doblar los requisitos de memoria y correr el riesgo de tratar de asignar un trozo contiguo de memoria que se ajuste a su objeto completo.

NOTA: estoy seguro de que hay mejores opciones que usar un List<string>() internamente, pero esto fue simple y resultó ser lo suficientemente bueno para mis propósitos.

public class StringBuilderEx 
{ 
    List<string> data = new List<string>(); 
    public void Append(string input) 
    { 
     data.Add(input); 
    } 
    public void AppendLine(string input) 
    { 
     data.Add(input + "\n"); 
    } 
    public void AppendLine() 
    { 
     data.Add("\n"); 
    } 

    /// <summary> 
    /// Copies all data to a String. 
    /// Warning: Will fail with an OutOfMemoryException if the data is too 
    /// large to fit into a single contiguous string. 
    /// </summary> 
    public override string ToString() 
    { 
     return String.Join("", data); 
    } 

    /// <summary> 
    /// Process Each section of the data in place. This avoids the 
    /// memory pressure of exporting everything to another contiguous 
    /// block of memory before processing. 
    /// </summary> 
    public void ForEach(Action<string> processData) 
    { 
     foreach (string item in data) 
      processData(item); 
    } 
} 

Ahora puede volcar todo el contenido en el archivo utilizando el siguiente código.

var stringData = new StringBuilderEx(); 
stringData.Append("Add lots of data"); 

using (StreamWriter file = new System.IO.StreamWriter(localFilename)) 
{ 
    stringData.ForEach((data) => 
    { 
     file.Write(data); 
    }); 
}