2013-07-23 13 views
104

Ich möchte Objekte zu Strings und zurück serialisieren.Stream in String und zurück konvertieren ... was fehlt uns?

Wir verwenden probobuf-net, um ein Objekt erfolgreich in einen Stream und zurück zu verwandeln.

Allerdings Stream zu String und zurück ... nicht so erfolgreich. Nachdem StreamToString und StringToStream durchgegangen wurde, ist das neue Stream nicht deserialisiert durch protobuf-net; es löst eine Arithmetic Operation resulted in an Overflow Ausnahme aus. Wenn wir den ursprünglichen Stream deserialisieren, funktioniert es.

Unsere Methoden:

public static string StreamToString(Stream stream) 
{ 
    stream.Position = 0; 
    using (StreamReader reader = new StreamReader(stream, Encoding.UTF8)) 
    { 
     return reader.ReadToEnd(); 
    } 
} 

public static Stream StringToStream(string src) 
{ 
    byte[] byteArray = Encoding.UTF8.GetBytes(src); 
    return new MemoryStream(byteArray); 
} 

Unser mit Beispielcode diese beiden:

MemoryStream stream = new MemoryStream(); 
Serializer.Serialize<SuperExample>(stream, test); 
stream.Position = 0; 
string strout = StreamToString(stream); 
MemoryStream result = (MemoryStream)StringToStream(strout); 
var other = Serializer.Deserialize<SuperExample>(result); 
+0

Zur Klärung bearbeitet, ty. – flipuhdelphia

+0

sollte nicht Stream MemoryStrea sein? – Ehsan

Antwort

46

Dies ist so üblich, aber so grundlegend falsch. Protobuf-Daten sind keine Zeichenfolgedaten. Es ist sicherlich kein ASCII. Sie verwenden die Codierung rückwärts. Ein Textcodierung Transfers:

  • eine beliebige Zeichenfolge Bytes
  • formatiert Bytes an den Original-String

Sie haben keine "formatiert Bytes" formatiert. Sie haben beliebige Bytes. Sie müssen etwas wie eine Base-n (allgemein: Base-64) Codierung verwenden. Dieser überträgt

  • beliebige Bytes auf eine formatierte Zeichenfolge
  • eine formatierte Zeichenfolge an den ursprünglichen Bytes

Blick auf Convert.ToBase64String und Konvertieren. FromBase64String

+1

könnten Sie eine ['BinaryFormatter'] (http://msdn.microsoft.com/en-us/library/system.runtime.serialization.formatters.binary.binaryformatter (v = vs.110) .aspx), ähnlich zu diesem [seltsamen Beispiel] (http://stackoverflow.com/a/1133465/1037948)? – drzaus

+0

@drzaus hm ... vielleicht nicht:> "Irgendwelche ungepaarten Ersatzzeichen sind in der binären Serialisierung verloren" – drzaus

+15

Nun, das ist das erste @drzaus ... Nie gesehen, dass jemand mit sich selbst auf SO redet. –

121

ich das gerade getestet und funktioniert einwandfrei.

string test = "Testing 1-2-3"; 

// convert string to stream 
byte[] byteArray = Encoding.ASCII.GetBytes(test); 
MemoryStream stream = new MemoryStream(byteArray); 

// convert stream to string 
StreamReader reader = new StreamReader(stream); 
string text = reader.ReadToEnd(); 

Wenn stream bereits geschrieben worden ist, könnten Sie vor dem ersten zu dem Anfang zu wagen wollen, bevor Sie den Text lesen out: stream.Seek(0, SeekOrigin.Begin);

5

Wenn Sie versuchen, mit UTF8 Encode Strom wie unter

Prüfung
var stream = new MemoryStream(); 
var streamWriter = new StreamWriter(stream, System.Text.Encoding.UTF8); 
Serializer.Serialize<SuperExample>(streamWriter, test); 
3

Versuchen Sie dies.

string output1 = Encoding.ASCII.GetString(byteArray, 0, byteArray.Length) 
0

In usecase wo Sie serialisieren möchten/deserialisieren POCOs ist Newtonsoft JSON-Bibliothek wirklich gut. Ich verwende es, um POCOs in SQL Server als JSON-Zeichenfolgen in einem Nvarchar-Feld beizubehalten. Vorbehalt ist, dass seit seiner nicht wahren De/Serialisierung private/geschützte Mitglieder und Klassenhierarchie nicht erhalten bleibt.

4

ein UTF8 Memorystream zu String-Konvertierung:

var res = Encoding.UTF8.GetString(stream.GetBuffer(),0 , stream.GetBuffer().Length) 
+0

Verwenden Sie stattdessen ToArray(). Der Puffer kann größer als die Größe der verwendeten Daten sein. ToArray() gibt eine Kopie der Daten mit der richtigen Größe zurück. 'var array = stream.ToArray(); var str = Kodierung.UTF8.GetString (Array, 0, Array.Länge); '. Siehe auch https://msdn.microsoft.com/en-us/library/system.io.memorystream.getbuffer.aspx?ranMID=24542&ranEAID=TnL5HPStwNw&ranSiteID=TnL5HPStwNw-fWxoHnp968IcSsgF87gs3g&tduid=(af5d64506773ff2a87e3cde51de009eb)(256380)(2459594)(TnL5HPStwNw- fWxoHnp968IcSsgF87gs3g)() – Mortennobel

0

schrieb ich eine nützliche Methode, alle Maßnahmen zu nennen, die eine StreamWriter nimmt und es zu schreiben, anstatt in einen String aus.Die Methode ist so;

static void SendStreamToString(Action<StreamWriter> action, out string destination) 
{ 
    using (var stream = new MemoryStream()) 
    using (var writer = new StreamWriter(stream, Encoding.Unicode)) 
    { 
     action(writer); 
     writer.Flush(); 
     stream.Position = 0; 
     destination = Encoding.Unicode.GetString(stream.GetBuffer(), 0, (int)stream.Length); 
    } 
} 

Und Sie können es so verwenden;

string myString; 

SendStreamToString(writer => 
{ 
    var ints = new List<int> {1, 2, 3}; 
    writer.WriteLine("My ints"); 
    foreach (var integer in ints) 
    { 
     writer.WriteLine(integer); 
    } 
}, out myString); 

Ich weiß, das viel einfacher, mit einem StringBuilder getan werden kann, ist der Punkt, dass Sie jede Methode aufrufen kann, die eine StreamWriter nimmt.

Verwandte Themen