Frage

Ich habe einen Byte-Array, das ich in einer Network lese. Die ersten beiden Bytes erzählen die Länge des Pakets, die folgt, und dann wird das Paket in ein Byte-Array von dieser Länge zu lesen. Die Daten in die ich von der Network / Byte-Array zu lesen, müssen hat ein paar Strings, d.h. variable Datenlänge durch neue Zeile Zeichen beendet, und einige feste Breite Felder wie Bytes und longs. So etwas wie folgt aus:

// I would have delimited these for clarity but I didn't want
// to imply that the stream was delimited because it's not.
StringbyteStringStringbytebytebytelonglongbytelonglong

ich weiß (und haben einige sagen, in), um das Format des Datenpakets, das über kommt, und was ich tun muss gelesen wird eine „Linie“ für jeden String-Wert, sondern eine feste Anzahl von Bytes für die Bytes gelesen und sehnt. Bisher meine vorgeschlagene Lösung ist eine while Schleife verwendet Bytes in einen temporären Byte-Array zu lesen, bis es ein Newline-Zeichen ist. Dann wandeln die Bytes in einen String. Dies scheint kludgy mir, aber ich weiß nicht eine andere offensichtliche Art und Weise sehen. Ich weiß, ich StreamReader.ReadLine() verwenden könnte, aber das würde einen anderen Strom beinhalten, und ich habe bereits eine NetworkStream. Aber wenn das die bessere Lösung, ich werde es versuchen.

Die andere Option, die ich in Betracht gezogen habe, ist mein Backend-Team Längen ein Byte oder zwei für diese Zeichenkette schreiben, so kann ich die Länge lesen und dann den String liest basierend auf der Länge angegeben.

So, wie Sie sehen können, habe ich einige Möglichkeiten, wie um dies zu realisieren, und ich möchte Sich Ihre Eingabe über das, was Sie den besten Weg, es zu tun in Betracht ziehen würden. Hier ist der Code, den ich gerade jetzt für als String in dem gesamten Paket zu lesen. Der nächste Schritt ist es, die verschiedene Felder des Pakets zu durchbrechen und tun, die eigentliche Programmierung Arbeit, die getan werden muss, Objekte Erstellung, Aktualisierung UI usw. auf der Grundlage der Daten in dem Paket.

string line = null;  
while (stream.DataAvailable)
{  
    //Get the packet length;  
    UInt16 packetLength = 0;  
    header = new byte[2];  
    stream.Read(header, 0, 2);  
    // Need to reverse the header array for BitConverter class if architecture is little endian.  
    if (BitConverter.IsLittleEndian)
        Array.Reverse(header);  
    packetLength = BitConverter.ToUInt16(header,0);

    buffer = new byte[packetLength];
    stream.Read(buffer, 0, BitConverter.ToUInt16(header, 0));
    line = System.Text.ASCIIEncoding.ASCII.GetString(buffer);
    Console.WriteLine(line);
}
War es hilfreich?

Lösung

Persönlich würde ich

  1. Setzen Sie ein Int16 zu Beginn der Strings, so dass Sie wissen, wie lange sie gehen zu sein, und
  2. Verwenden Sie die IO.BinaryReader Klasse das Lesen tun, es wird „lesen“, Ints, strings, Zeichen usw. in variable z.B. BinReader.ReadInt16 () zwei Bytes gelesen wird, kehren die int16 sie vertreten, und auf zwei Bytes bewegen im Strom

Hope, das hilft.

P. S. Seien Sie vorsichtig mit der Readstring-Methode, nimmt es die Zeichenfolge mit benutzerdefinierten 7 Bit-Integer vorangestellt das heißt, dass es durch die Klasse Binary geschrieben wurde. Hier finden Sie von dieser MS-Office- Post

  

Die Klasse Binary hat zwei Methoden   für Streicher zu schreiben: die überlasteten   Write () Methode und die Write ()   Methode. Der ehemalige schreibt die Zeichenfolge   als ein Strom von Bytes, nach dem   die Klasse codiert, verwendet wird. Das   Write () Methode auch die Verwendungen   angegebene Codierung, aber es Präfixe   die Zeichenfolge des Strom von Bytes mit der   tatsächliche Länge des Strings. Eine solche   gelegten Strings gelesen zurück in über   BinaryReader.ReadString ().

     

Das Interessante an der Länge   schätzen es, dass so wenige Bytes wie möglich   werden verwendet, diese Größe zu halten, ist es   als eine Art gespeichert, um einen 7-Bit genannt   codierte ganze Zahl ist. Wenn die Länge passt   7 Bits ein einzelnes Byte verwendet wird, wenn es sich um   größer als dieser dann dem High-Bit auf   das erste Byte festgelegt ist und ein zweiter   Byte wird durch Verschieben des Wertes geschaffen   um 7 Bits. Dies wird wiederholt, mit   aufeinanderfolgende Bytes, bis es   genug Bytes den Wert zu halten. Diese   Mechanismus wird verwendet, um sicherzustellen, dass   die Länge nicht zu einem   erheblicher Teil der Größe genommen   up von dem serialisierten String.   Binary und Binary haben   Verfahren 7-Bit lesen und schreiben,   codierte ganze Zahlen, aber sie sind   nur geschützt und so können Sie verwenden,   wenn Sie von diesen Klassen abgeleitet werden.

Andere Tipps

Ich würde mit Länge-Präfix-Strings. Es wird Ihr Leben viel einfacher, und es bedeutet, dass Sie Strings mit Zeilenumbrüchen in ein paar Kommentare zu Ihrem Code darstellen können aber:.

  • Sie nicht Stream.DataAvailable verwenden. Nur weil es keine Daten verfügbar ist jetzt bedeutet nicht das Ende des Stroms gelesen habe.
  • Wenn Sie nicht absolut sicher sind, werden Sie nie Text über ASCII benötigen, nicht ASCIIEncoding nicht verwendet werden.
  • Gehen Sie nicht davon, dass Stream.Read alle Daten lesen, werden Sie danach zu fragen. immer überprüfen Sie den Rückgabewert.
  • macht Binary viel dies viel einfacher (einschließlich Länge-Präfix Streicher und liest, die bis zum Schleifen es gelesen hat, was Sie es gefragt haben zu)
  • Du nennt BitConverter.ToUInt16 zweimal auf den gleichen Daten. Warum?
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top