簡體   English   中英

從字節數組讀取行(不將字節數組轉換為字符串)

[英]Read line from byte array (not convert byte array to string)

我有一個字節數組,我正在從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 但如果這是更好的解決方案,我會試一試。

我考慮的另一個選項是讓我的后端團隊為那些String值的長度寫一個或兩個字節,這樣我就可以讀取長度,然后根據指定的長度讀取字符串。

所以,正如你所看到的,我有一些選擇如何解決這個問題,我希望你的意見是關於你認為最好的方法。 這是我現在用於以字符串形式讀取整個數據包的代碼。 下一步是打破數據包的各個字段,並根據數據包中的數據完成需要完成的實際編程工作,創建對象,更新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);
}

就我個人而言

  1. 把一個Int16放在字符串的開頭,這樣你就可以知道它們將會持續多長時間,並且
  2. 使用IO.BinaryReader類進行讀取,它將“讀取”,整數,字符串,字符等變為變量,例如BinReader.ReadInt16()將讀取兩個字節,返回它們表示的int16,並在其中移動兩個字節流

希望這可以幫助。

PS小心使用ReadString方法,它假定字符串前面有自定義的7位整數,即它是由BinaryWriter類編寫的。 以下是來自CodeGuru的帖子

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

關於長度值的有趣之處在於,盡可能少的字節用於保存此大小,它被存儲為稱為7位編碼整數的類型。 如果長度適合7位,則使用單個字節,如果大於此,則設置第一個字節的高位,並通過將值移位7位來創建第二個字節。 這將以連續的字節重復,直到有足夠的字節來保存該值。 此機制用於確保長度不會成為序列化字符串占用的大小的重要部分。 BinaryWriter和BinaryReader具有讀取和寫入7位編碼整數的方法,但它們受到保護,因此只有從這些類派生時才能使用它們。

我會選擇長度為前綴的字符串。 它會讓你的生活變得更簡單,這意味着你可以用換行符來表示字符串。雖然對你的代碼有一些評論:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM