.net - utf8 - ¿Cómo se obtiene una cadena de un MemoryStream?
memorystream to string c# (10)
Si me dan un MemoryStream
que sé que se ha rellenado con una String
, ¿cómo puedo volver a sacar una String
?
¿Por qué no hacer un método de extensión agradable en el tipo de MemoryStream?
public static class MemoryStreamExtensions
{
static object streamLock = new object();
public static void WriteLine(this MemoryStream stream, string text, bool flush)
{
byte[] bytes = Encoding.UTF8.GetBytes(text + Environment.NewLine);
lock (streamLock)
{
stream.Write(bytes, 0, bytes.Length);
if (flush)
{
stream.Flush();
}
}
}
public static void WriteLine(this MemoryStream stream, string formatString, bool flush, params string[] strings)
{
byte[] bytes = Encoding.UTF8.GetBytes(String.Format(formatString, strings) + Environment.NewLine);
lock (streamLock)
{
stream.Write(bytes, 0, bytes.Length);
if (flush)
{
stream.Flush();
}
}
}
public static void WriteToConsole(this MemoryStream stream)
{
lock (streamLock)
{
long temporary = stream.Position;
stream.Position = 0;
using (StreamReader reader = new StreamReader(stream, Encoding.UTF8, false, 0x1000, true))
{
string text = reader.ReadToEnd();
if (!String.IsNullOrEmpty(text))
{
Console.WriteLine(text);
}
}
stream.Position = temporary;
}
}
}
Por supuesto, tenga cuidado al usar estos métodos junto con los estándares. :) ... tendrá que usar ese práctico streamLock si lo hace, para la concurrencia.
En este caso, si realmente desea utilizar el método ReadToEnd
en MemoryStream
de una manera fácil, puede usar este Método de extensión para lograr esto:
public static class SetExtensions
{
public static string ReadToEnd(this MemoryStream BASE)
{
BASE.Position = 0;
StreamReader R = new StreamReader(BASE);
return R.ReadToEnd();
}
}
Y puedes usar este método de esta manera:
using (MemoryStream m = new MemoryStream())
{
//for example i want to serialize an object into MemoryStream
//I want to use XmlSeralizer
XmlSerializer xs = new XmlSerializer(_yourVariable.GetType());
xs.Serialize(m, _yourVariable);
//the easy way to use ReadToEnd method in MemoryStream
MessageBox.Show(m.ReadToEnd());
}
Este ejemplo muestra cómo leer una cadena desde un MemoryStream, en la que he usado una serialización (usando DataContractJsonSerializer), pasar la cadena de algún servidor al cliente y luego, cómo recuperar MemoryStream de la cadena pasada como parámetro, luego , deserializa el MemoryStream.
He usado partes de diferentes publicaciones para realizar esta muestra.
Espero que esto ayude.
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Threading;
namespace JsonSample
{
class Program
{
static void Main(string[] args)
{
var phones = new List<Phone>
{
new Phone { Type = PhoneTypes.Home, Number = "28736127" },
new Phone { Type = PhoneTypes.Movil, Number = "842736487" }
};
var p = new Person { Id = 1, Name = "Person 1", BirthDate = DateTime.Now, Phones = phones };
Console.WriteLine("New object ''Person'' in the server side:");
Console.WriteLine(string.Format("Id: {0}, Name: {1}, Birthday: {2}.", p.Id, p.Name, p.BirthDate.ToShortDateString()));
Console.WriteLine(string.Format("Phone: {0} {1}", p.Phones[0].Type.ToString(), p.Phones[0].Number));
Console.WriteLine(string.Format("Phone: {0} {1}", p.Phones[1].Type.ToString(), p.Phones[1].Number));
Console.Write(Environment.NewLine);
Thread.Sleep(2000);
var stream1 = new MemoryStream();
var ser = new DataContractJsonSerializer(typeof(Person));
ser.WriteObject(stream1, p);
stream1.Position = 0;
StreamReader sr = new StreamReader(stream1);
Console.Write("JSON form of Person object: ");
Console.WriteLine(sr.ReadToEnd());
Console.Write(Environment.NewLine);
Thread.Sleep(2000);
var f = GetStringFromMemoryStream(stream1);
Console.Write(Environment.NewLine);
Thread.Sleep(2000);
Console.WriteLine("Passing string parameter from server to client...");
Console.Write(Environment.NewLine);
Thread.Sleep(2000);
var g = GetMemoryStreamFromString(f);
g.Position = 0;
var ser2 = new DataContractJsonSerializer(typeof(Person));
var p2 = (Person)ser2.ReadObject(g);
Console.Write(Environment.NewLine);
Thread.Sleep(2000);
Console.WriteLine("New object ''Person'' arrived to the client:");
Console.WriteLine(string.Format("Id: {0}, Name: {1}, Birthday: {2}.", p2.Id, p2.Name, p2.BirthDate.ToShortDateString()));
Console.WriteLine(string.Format("Phone: {0} {1}", p2.Phones[0].Type.ToString(), p2.Phones[0].Number));
Console.WriteLine(string.Format("Phone: {0} {1}", p2.Phones[1].Type.ToString(), p2.Phones[1].Number));
Console.Read();
}
private static MemoryStream GetMemoryStreamFromString(string s)
{
var stream = new MemoryStream();
var sw = new StreamWriter(stream);
sw.Write(s);
sw.Flush();
stream.Position = 0;
return stream;
}
private static string GetStringFromMemoryStream(MemoryStream ms)
{
ms.Position = 0;
using (StreamReader sr = new StreamReader(ms))
{
return sr.ReadToEnd();
}
}
}
[DataContract]
internal class Person
{
[DataMember]
public int Id { get; set; }
[DataMember]
public string Name { get; set; }
[DataMember]
public DateTime BirthDate { get; set; }
[DataMember]
public List<Phone> Phones { get; set; }
}
[DataContract]
internal class Phone
{
[DataMember]
public PhoneTypes Type { get; set; }
[DataMember]
public string Number { get; set; }
}
internal enum PhoneTypes
{
Home = 1,
Movil = 2
}
}
Este ejemplo muestra cómo leer y escribir una cadena en un MemoryStream.
Imports System.IO
Module Module1
Sub Main()
'' We don''t need to dispose any of the MemoryStream
'' because it is a managed object. However, just for
'' good practice, we''ll close the MemoryStream.
Using ms As New MemoryStream
Dim sw As New StreamWriter(ms)
sw.WriteLine("Hello World")
'' The string is currently stored in the
'' StreamWriters buffer. Flushing the stream will
'' force the string into the MemoryStream.
sw.Flush()
'' If we dispose the StreamWriter now, it will close
'' the BaseStream (which is our MemoryStream) which
'' will prevent us from reading from our MemoryStream
''sw.Dispose()
'' The StreamReader will read from the current
'' position of the MemoryStream which is currently
'' set at the end of the string we just wrote to it.
'' We need to set the position to 0 in order to read
'' from the beginning.
ms.Position = 0
Dim sr As New StreamReader(ms)
Dim myStr = sr.ReadToEnd()
Console.WriteLine(myStr)
'' We can dispose our StreamWriter and StreamReader
'' now, though this isn''t necessary (they don''t hold
'' any resources open on their own).
sw.Dispose()
sr.Dispose()
End Using
Console.WriteLine("Press any key to continue.")
Console.ReadKey()
End Sub
End Module
Las soluciones anteriores no funcionarían en los casos en que la codificación está involucrada. Aquí está - una especie de "vida real" - ejemplo de cómo hacerlo correctamente ...
using(var stream = new System.IO.MemoryStream())
{
var serializer = new DataContractJsonSerializer(typeof(IEnumerable<ExportData>), new[]{typeof(ExportData)}, Int32.MaxValue, true, null, false);
serializer.WriteObject(stream, model);
var jsonString = Encoding.Default.GetString((stream.ToArray()));
}
También puedes usar
Encoding.ASCII.GetString(ms.ToArray());
No creo que esto sea menos eficiente, pero no podría jurarlo. También le permite elegir una codificación diferente, mientras que con un StreamReader tendría que especificar eso como un parámetro.
Una versión ligeramente modificada de la respuesta de Brian permite la administración opcional del inicio de lectura. Este parece ser el método más fácil. Probablemente no sea el más eficiente, pero fácil de entender y usar.
Public Function ReadAll(ByVal memStream As MemoryStream, Optional ByVal startPos As Integer = 0) As String
'' reset the stream or we''ll get an empty string returned
'' remember the position so we can restore it later
Dim Pos = memStream.Position
memStream.Position = startPos
Dim reader As New StreamReader(memStream)
Dim str = reader.ReadToEnd()
'' reset the position so that subsequent writes are correct
memStream.Position = Pos
Return str
End Function
Utilizando un StreamReader para convertir MemoryStream en una cadena.
<Extension()> _
Public Function ReadAll(ByVal memStream As MemoryStream) As String
'' Reset the stream otherwise you will just get an empty string.
'' Remember the position so we can restore it later.
Dim pos = memStream.Position
memStream.Position = 0
Dim reader As New StreamReader(memStream)
Dim str = reader.ReadToEnd()
'' Reset the position so that subsequent writes are correct.
memStream.Position = pos
Return str
End Function
use un StreamReader , luego puede usar el método ReadToEnd que devuelve una cadena.
byte[] array = Encoding.ASCII.GetBytes("MyTest1 - MyTest2");
MemoryStream streamItem = new MemoryStream(array);
// convert to string
StreamReader reader = new StreamReader(streamItem);
string text = reader.ReadToEnd();