wake-up-neo.com

Konvertieren von Stream in String und zurück ... Was fehlt uns?

Ich möchte Objekte zu Strings und zurück serialisieren.

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

Stream to string und zurück ... jedoch nicht so erfolgreich. Nach Durchlaufen von StreamToString und StringToStream ist die neue Stream nicht. es wird eine Arithmetic Operation resulted in an Overflow-Ausnahme ausgelöst. Wenn wir den ursprünglichen Stream deserialisieren, funktioniert er.

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 Beispielcode mit diesen 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);
132
flipuhdelphia

Dies ist so häufig, aber zutiefst falsch. Protobuf-Daten sind keine String-Daten. Es ist sicherlich kein ASCII. Sie verwenden die Kodierung rückwärts . Eine Textcodierungsübertragung:

  • eine beliebige Zeichenfolge für formatierte Bytes
  • formatierte Bytes in die ursprüngliche Zeichenfolge

Sie haben keine "formatierten Bytes". Sie haben beliebige Bytes. Sie müssen etwas wie eine base-n-Kodierung (üblicherweise: base-64) verwenden. Diese Übertragungen

  • beliebige Bytes in eine formatierte Zeichenfolge
  • eine formatierte Zeichenfolge zu den ursprünglichen Bytes

schauen Sie sich Convert.ToBase64String und Convert an. FromBase64String

51
Marc Gravell

Ich habe das gerade getestet und funktioniert gut.

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 wurde, sollten Sie vor dem ersten Lesen des Texts den Anfang suchen: stream.Seek(0, SeekOrigin.Begin);

164
Ehsan

Versuchen Sie beim Testen mit UTF8 Encode wie unten beschrieben 

var stream = new MemoryStream();
var streamWriter = new StreamWriter(stream, System.Text.Encoding.UTF8);
Serializer.Serialize<SuperExample>(streamWriter, test);
5
Damith

Versuche dies.

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

eine UTF8 MemoryStream-zu-String-Konvertierung:

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

Ich habe eine nützliche Methode geschrieben, um eine beliebige Aktion aufzurufen, die eine StreamWriter verwendet, und sie stattdessen in eine Zeichenfolge zu schreiben. 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 du kannst es so benutzen;

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ß, dass dies mit einer StringBuilder viel einfacher geht. Der Punkt ist, dass Sie jede Methode aufrufen können, die eine StreamWriter benötigt.

2
Steztric

Ich möchte Objekte zu Strings und zurück serialisieren.

Anders als die anderen Antworten, aber der einfachste Weg, genau das für die meisten Objekttypen zu tun, ist XmlSerializer:

        Subject subject = new Subject();
        XmlSerializer serializer = new XmlSerializer(typeof(Subject));
        using (Stream stream = new MemoryStream())
        {
            serializer.Serialize(stream, subject);
            // do something with stream
            Subject subject2 = (Subject)serializer.Deserialize(stream);
            // do something with subject2
        }

Alle Ihre öffentlichen Eigenschaften der unterstützten Typen werden serialisiert. Sogar einige Auflistungsstrukturen werden unterstützt und führen zu Unterobjekteigenschaften. Sie können steuern, wie die Serialisierung mit attributes in Ihren Eigenschaften arbeitet.

Dies funktioniert nicht bei allen Objekttypen. Einige Datentypen werden für die Serialisierung nicht unterstützt, aber insgesamt ist sie ziemlich leistungsfähig und Sie müssen sich keine Gedanken um die Kodierung machen. 

0
Denise Skidmore

In Usecase, wo Sie POCOs serialisieren/deserialisieren möchten, ist die JSON-Bibliothek von Newtonsoft wirklich gut. Ich benutze es, um POCOs in SQL Server als JSON-Zeichenfolgen in einem NVar-Feld zu erhalten. Der Nachteil ist jedoch, dass private/geschützte Mitglieder und Klassenhierarchie nicht beibehalten werden, da sie nicht wirklich de/serialization ist. 

0
MD Luffy