2009-12-10 18 views

Respuesta

702
public static Stream GenerateStreamFromString(string s) 
{ 
    var stream = new MemoryStream(); 
    var writer = new StreamWriter(stream); 
    writer.Write(s); 
    writer.Flush(); 
    stream.Position = 0; 
    return stream; 
} 

No se olvide de usar Usando: no estando dispuestos

using (var stream = GenerateStreamFromString("a,b \n c,d")) 
{ 
    // ... Do stuff to stream 
} 

Sobre el StreamWriter. StreamWriter es solo una envoltura alrededor de la transmisión base y no utiliza ningún recurso que deba desecharse. El método Dispose cerrará el Stream subyacente en el que StreamWriter está escribiendo. En este caso, ese es el MemoryStream que queremos devolver.

En .NET 4.5 ahora hay una sobrecarga para StreamWriter que mantiene la secuencia subyacente abierta después de que se elimina el escritor, pero este código hace lo mismo y funciona con otras versiones de .NET también.

Ver Is there any way to close a StreamWriter without closing its BaseStream?

+98

Un concepto de punto importante para señalar es que una secuencia se compone de bytes, mientras que una cadena se compone de caracteres. Es crucial entender que la conversión de un carácter a uno o más bytes (o a un flujo como en este caso) __siempre__ usa (o asume) una codificación particular. Esta respuesta, aunque correcta en algunos casos, utiliza la codificación predeterminada, y puede no ser adecuada en general. Pasar explícitamente una codificación al constructor de StreamWriter haría más evidente que el autor necesita considerar las implicaciones de la codificación. – ricovox

+2

Usted dice "No se olvide de usar el Uso" para usar la transmisión, pero en su método 'GenerateStreamFromString' no está usando el Uso con StreamWriter. ¿Hay alguna razón para esto? – Ben

+6

@Ben Sí. Si descarta StreamWriter, la transmisión subyacente también se cerrará. No queremos eso. La única razón por la que el escritor es desechable es limpiar la secuencia, por lo que es seguro ignorarla. –

20

utilizar la clase MemoryStream, llamando Encoding.GetBytes para convertir su cadena en una matriz de bytes en primer lugar.

¿Necesita posteriormente un TextReader en la secuencia? Si es así, se puede suministrar una StringReader directamente, sin pasar por el MemoryStream y Encoding pasos.

9

Aquí van:

private Stream GenerateStreamFromString(String p) 
{ 
    Byte[] bytes = UTF8Encoding.GetBytes(p); 
    MemoryStream strm = new MemoryStream(); 
    strm.Write(bytes, 0, bytes.Length); 
    return strm; 
} 
+1

La posición debe restablecerse después de la escritura. Es mejor usar el constructor, como en la respuesta de joelnet. –

529

Otra solución:

public static MemoryStream GenerateStreamFromString(string value) 
{ 
    return new MemoryStream(Encoding.UTF8.GetBytes(value ?? "")); 
} 
+22

En caso de que alguien lo use con una cadena XML Deserialización, tuve que cambiar UTF8 a Unicode para que funcione sin una bandera. ¡¡¡Buena publicación!!! – Gaspa79

+1

Me gusta este (con el ajuste de Rhyous y el azúcar extra trivial para usar como método de extensión) mejor que la respuesta aceptada; más flexible, menos LOC y menos objetos involucrados (sin necesidad explícita de un StreamWriter) – KeithS

+0

'new MemoryStream (Encoding.UTF8.GetBytes (" \ ufeff "+ (value ??" "))' si necesita tener la lista de materiales incluido al principio de la secuencia – robert4

97

añadir esto a una clase de utilidad cadena estática:

public static Stream ToStream(this string str) 
{ 
    MemoryStream stream = new MemoryStream(); 
    StreamWriter writer = new StreamWriter(stream); 
    writer.Write(str); 
    writer.Flush(); 
    stream.Position = 0; 
    return stream; 
} 

Esto añade una función de extensión para que pueda simplemente:

using (var stringStream = "My string".ToStream()) 
{ 
    // use stringStream 
} 
+2

Descubrí que la secuencia devuelta se cierra (causando excepciones semialeatorias) cuando el recolector de basura limpia el 'StreamWriter'. La solución era usar un constructor diferente, uno que me permitiera especificar ** leaveOpen **. – Bevan

-1
/// <summary> 
/// Get Byte[] from String 
/// </summary> 
/// <param name="str"></param> 
/// <returns></returns> 
public static byte[] GetBytes(string str) 
{ 
    byte[] bytes = new byte[str.Length * sizeof(char)]; 
    System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length); 
    return bytes; 
} 

/// <summary> 
/// Get Stream from String 
/// </summary> 
/// <param name="str"></param> 
/// <returns></returns> 
public static Stream GetStream(string str) 
{ 
    return new MemoryStream(GetBytes(str)); 
} 
+2

System.String es siempre UTF-16. ¿No es así? – abatishchev

+3

Usted dice" No es necesario saber que la codificación de cadenas funciona. "Es como decir que no importa de qué color sea tu coche porque vas a volcar pintura verde por todas partes. Como abatishchev p salidos, usted está usando la codificación UTF-16 desconocidamente para convertir la cadena a bytes. Digamos que ahora escribe el contenido de esta secuencia en un archivo y lo abre como un archivo de texto. Verás espacios entre cada personaje. – ricovox

-1

Una buena combinación de extensiones de Cuerda:

public static byte[] GetBytes(this string str) 
{ 
    byte[] bytes = new byte[str.Length * sizeof(char)]; 
    System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length); 
    return bytes; 
} 

public static Stream ToStream(this string str) 
{ 
    Stream StringStream = new MemoryStream(); 
    StringStream.Read(str.GetBytes(), 0, str.Length); 
    return StringStream; 
} 
33
public Stream GenerateStreamFromString(string s) 
{ 
    return new MemoryStream(Encoding.UTF8.GetBytes(s)); 
} 
8

utilicé una mezcla de respuestas como esta:

public static Stream ToStream(this string str, Encoding enc = null) 
{ 
    enc = enc ?? Encoding.UTF8; 
    return new MemoryStream(enc.GetBytes(str ?? "")); 
} 

Y entonces utilizar de esta manera:

String someStr="This is a Test"; 
Encoding enc = getEncodingFromSomeWhere(); 
using (Stream stream = someStr.ToStream(enc)) 
{ 
    // Do something with the stream.... 
} 
+0

Thomas, ¿por qué votar? enc = enc? Encoding.UTF8 me permite preguntar específicamente stream con codificación específica, o un valor por defecto de UTF8, y porque en .net (en la medida en que lo uso .net 4.0) no se puede dar un tipo de referencia que no sea un valor por defecto en la función la firma de esta línea es necesaria, ¿tiene sentido? – Robocide

+0

mencionando que necesita poner esto en una clase separada (¿clase estática no genérica?) También es útil y reduce los votos a la baja. – Ali

4

Utilizamos los métodos de extensión que se enumeran a continuación. Creo que debes hacer que el desarrollador tome una decisión sobre la codificación, por lo que hay menos magia involucrada.

public static class StringExtensions { 

    public static Stream ToStream(this string s) { 
     return s.ToStream(Encoding.UTF8); 
    } 

    public static Stream ToStream(this string s, Encoding encoding) { 
     return new MemoryStream(encoding.GetBytes(s ?? "")); 
    } 
} 
+0

Preferiría implementar el primer método como 'return ToStream (s, Encoding.UTF8);'. En la implementación actual ('return s.ToStream (Encoding.UTF8);', el desarrollador se ve obligado a pensar más en captar el código y parece que el caso de 's == null' no se maneja y arroja' NullReferenceException'. – Palec

0

ligeramente modificada versión de los métodos de extensión que se sugieren en un comentario de respuesta y respuesta @Shaun Bowe @ de JoelNet. Porque estoy de acuerdo con el comentario de @Palec.

public static Stream ToStream(this string value) => ToStream(value, Encoding.UTF8); 

public static Stream ToStream(this string value, Encoding encoding) => new MemoryStream(encoding.GetBytes(value ?? string.Empty)); 
Cuestiones relacionadas