[英]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);
}
就我個人而言
希望這可以幫助。
PS小心使用ReadString方法,它假定字符串前面有自定義的7位整數,即它是由BinaryWriter類編寫的。 以下是來自CodeGuru的帖子
BinaryWriter類有兩種寫字符串的方法:重載的Write()方法和WriteString()方法。 前者根據類正在使用的編碼將字符串寫為字節流。 WriteString()方法也使用指定的編碼,但它將字符串的字節流作為字符串實際長度的前綴。 這些帶前綴的字符串通過BinaryReader.ReadString()讀回。
關於長度值的有趣之處在於,盡可能少的字節用於保存此大小,它被存儲為稱為7位編碼整數的類型。 如果長度適合7位,則使用單個字節,如果大於此,則設置第一個字節的高位,並通過將值移位7位來創建第二個字節。 這將以連續的字節重復,直到有足夠的字節來保存該值。 此機制用於確保長度不會成為序列化字符串占用的大小的重要部分。 BinaryWriter和BinaryReader具有讀取和寫入7位編碼整數的方法,但它們受到保護,因此只有從這些類派生時才能使用它們。
我會選擇長度為前綴的字符串。 它會讓你的生活變得更簡單,這意味着你可以用換行符來表示字符串。雖然對你的代碼有一些評論:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.