Domanda

Ho un array di byte che sto leggendo da un NetworkStream.I primi due byte raccontare la lunghezza del pacchetto, che segue e quindi il pacchetto viene letto in una matrice di byte di lunghezza.I dati che ho bisogno di leggere il NetworkStream/array di byte ha un paio di Stringhe, ovveroi dati di lunghezza variabile terminato da caratteri di nuova riga, e alcuni campi a larghezza fissa come byte e sospira.Quindi, qualcosa di simile a questo:

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

Io so (e hanno alcuni dicono in) formato del pacchetto di dati che sta arrivando attraverso, e quello che devo fare è leggere una "linea" per ogni valore di stringa, ma leggere un numero fisso di byte per byte e sospira.Finora, la mia proposta di soluzione è usare un while ciclo per leggere i byte in un temp matrice di byte fino a quando non c'è un carattere di newline.Quindi, convertire i byte in una stringa.Questo sembra difettose per me, ma non vedo altro modo evidente.Mi rendo conto che potrei utilizzare StreamReader.ReadLine() ma che comporterebbe un altro stream e ho già un NetworkStream.Ma se quella è la soluzione migliore, vado a dare un colpo.

L'altra opzione che ho considerato è di avere il mio backend team di scrivere un byte (o due) per i valori di Stringa' lunghezze in modo che io possa leggere la lunghezza e poi leggere la Stringa in base alla lunghezza specificata.

Quindi, come potete vedere, ho alcune opzioni per come fare questo, e vorrei il vostro ingresso su ciò che si dovrebbe prendere in considerazione il modo migliore per farlo.Ecco il codice che ho in questo momento per la lettura dell'intero pacchetto come una stringa.Il passo successivo è quello di rompere i vari campi del pacchetto e fare il lavoro di programmazione che deve essere fatto per la creazione di oggetti, l'aggiornamento dell'interfaccia utente, etc.in base ai dati del pacchetto.

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);
}
È stato utile?

Soluzione

Personalmente mi sento di

  1. Mettere un Int16 all'inizio del le stringhe, in modo da sapere quanto tempo si sta andando ad essere, e
  2. Uso IO.BinaryReader classe a fare la lettura, sarà "leggere", int, stringhe, caratteri ecc variabili, ad es.BinReader.ReadInt16() per leggere due byte, restituire il int16 che essi rappresentano, e spostare due byte nel flusso

Spero che questo aiuta.

P. S.Prestare attenzione a utilizzare il metodo ReadString, si assume la stringa viene anteposto personalizzato 7 bit interi cioèche è stato scritto dalla BinaryWriter classe.Il seguente è da questo CodeGuru post

Il BinaryWriter classe dispone di due metodi per la scrittura di stringhe:il sovraccarico Metodo Write() e il WriteString() metodo.L'ex scrive la stringa come un flusso di byte in base al che codifica per la classe che si sta utilizzando.Il WriteString() metodo utilizza anche il codifica specificata, ma è prefissi la stringa s stream di byte, con la lunghezza effettiva della stringa.Tali prefisso stringhe sono riletta via BinaryReader.ReadString().

La cosa interessante circa la lunghezza valore che come pochi byte possibile sono utilizzati per tenere questa dimensione, è archiviato come un tipo chiamato a 7 bit intero codificato.Se la lunghezza adatta 7 bit di un byte viene utilizzato, se è maggiore di questo, allora il bit su il primo byte è impostato e un secondo il byte è creato spostando il valore da 7 bit.Questo è ripetuto con byte successivi fino a che non ci sono numero di byte sufficiente per contenere il valore.Questo è il meccanismo utilizzato per assicurarsi che la lunghezza non deve diventare un parte significativa delle dimensioni prese da stringa serializzata.BinaryWriter e BinaryReader hanno i metodi per leggere e scrivere 7-bit codifica dei numeri interi, ma sono protetta e quindi si possono usare solo se si deriva da queste classi.

Altri suggerimenti

Vorrei andare con lunghezza prefisso di stringhe.Renderà la vostra vita molto più semplice, e questo significa che è possibile rappresentare le stringhe con le interruzioni di riga.Un paio di commenti nel codice, però:

  • Non utilizzare il Flusso.DataAvailable.Solo perché non ci sono dati disponibili ora non significa che non hai letto la fine del flusso.
  • A meno che non siate assolutamente sicuri che non avrete mai bisogno di testo al di là di ASCII, non utilizzare ASCIIEncoding.
  • Non date per scontato che il Flusso.Leggere leggere tutti i dati che chiedi. Sempre controllare il valore di ritorno.
  • BinaryReader fa un sacco di questo è molto più facile (compresa la lunghezza del prefisso stringhe e una Lettura che si ripete fino a quando è leggere ciò che hai richiesto)
  • Si chiama BitConverter.ToUInt16 due volte gli stessi dati.Perché?
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top