2009-01-29 238 views
6

我有一個字節數組,我從NetworkStream中讀取數據。前兩個字節表示隨後的數據包的長度,然後將數據包讀入該長度的字節數組中。我需要從NetworkStream/byte數組中讀取的數據有幾個字符串,即可變長度數據以新行字符結尾,以及一些固定寬度的字段,如字節和長整型。所以,這樣的事情:從字節數組讀取行(不將字節數組轉換爲字符串)

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

我知道(並有一定的說,在),其跨來的數據包的格式,我需要做的是閱讀每個字符串值「線」是什麼,但讀取字節和長整數的字節數。到目前爲止,我提出的解決方案是使用while循環將字節讀入臨時字節數組,直到出現換行符爲止。然後,將字節轉換爲字符串。這對我來說似乎很笨拙,但我沒有看到另一種明顯的方式。我意識到我可以使用StreamReader.ReadLine(),但這將涉及另一個流,我已經有一個NetworkStream。但如果這是更好的解決方案,我會給它一個機會。

我考慮的另一個選擇是讓我的後端團隊爲這些字符串值的長度寫入一個或兩個字節,以便我可以讀取長度,然後根據指定的長度讀取字符串。因此,正如你所看到的,我有一些關於如何解決這個問題的選擇,並且我希望你對你認爲最好的方式提出意見。以下是我現在用於讀取整個數據包的字符串的代碼。下一步是打破數據包的各個領域,根據數據包中的數據完成需要完成的實際編程工作,創建對象,更新UI等。

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); 
} 

回答

9

我個人

  1. 把一個Int16類型的 字符串的開始,所以你知道他們要去 要等多久,並
  2. 使用IO.BinaryReader類到 做的讀,它會「讀」,整數, 字符串,字符等等變量變量BinReader.ReadInt16()將讀取兩個字節,返回它們表示的int16,並在流中移動兩個字節

希望這有助於。

P.S.使用ReadString方法時要小心,它假設該字符串前面是自定義的7位整數,即它是由BinaryWriter類寫入的。 以下是這CodeGuru

的的BinaryWriter類有字符串寫入兩種方法 :重載 Write()方法和WriteString()方法 。前者根據 編碼類所使用的字節流將字符串 寫入。 WriteString()方法也使用 指定的編碼,但它將 字符串的字節流與 字符串的實際長度作爲前綴。這樣的 前綴字符串通過 BinaryReader.ReadString()讀回。

繞長度 值有趣的認爲儘可能 爲幾個字節用於保存這個大小,它是 存儲爲所謂的7位 編碼整數類型。如果長度適合於7位,則使用單個字節,如果它大於 ,則第一個字節被設置爲 的高位,並且通過將值 移位7位來創建第二個 字節。這是連續字節 重複,直到有 足夠的字節來保存該值。這個機制用於確保 的長度不會成爲 大小的一部分,其大小取決於序列化的字符串所帶的大小 。 BinaryWriter和BinaryReader有 方法讀取和寫入7位 編碼整數,但它們是 受保護,因此如果您從這些類派生,則只能使用它們 。

+0

以前沒有遇到過BinaryReader。這看起來對於我正在處理的所有這些東西都是非常有幫助的。謝謝! – jxpx777 2009-01-29 17:09:07

5

我會去與長度前綴的字符串。它將使你的生活簡單得多,它意味着你可以代表與換行符字符串在代碼的一些意見,雖然:

  • 不要使用Stream.DataAvailable。僅僅因爲沒有可用的數據現在並不意味着你已經閱讀了流的結尾。
  • 除非你確定你永遠不需要超出ASCII的文本,否則不要使用ASCIIEncoding。
  • 不要以爲Stream.Read會讀取您要求的所有數據。 總是檢查返回值。
  • BinaryReader使這很容易很多(包括長度前綴字符串和一個讀取循環,直到它被讀取您要求的內容)
  • 您在相同的數據上調用BitConverter.ToUInt16兩次。爲什麼?
相關問題