今天偶然發現一個問題——字符串字節獲取的方式不同會導致獲取的結果不一樣。
定義如下方法,用於獲取字符串的字節:
1 static byte[] GetBytes(string data) 2 { 3 using (MemoryStream ms = new MemoryStream()) 4 { 5 using (BinaryWriter bw = new BinaryWriter(ms)) 6 { 7 bw.Write(data); 8 9 } 10 return ms.ToArray(); 11 } 12 }
以下方式也可以獲取字符串對應的字節:
1 UTF8Encoding encoding = new UTF8Encoding(); 2 int len1 = encoding.GetBytes(name).Length;
測試:
1 static void Main(string[] args) 2 { 3 string name = "123"; 4 5 UTF8Encoding encoding = new UTF8Encoding(); 6 int len1 = encoding.GetBytes(name).Length; 7 8 int len2 = GetBytes(name).Length; 9 10 Console.WriteLine($"len1 = {len1} \n\nlen2 = {len2}"); 11 12 Console.ReadKey(); 13 }
輸出:
值不一樣,為什么?
BinaryWriter 並沒有正常地寫入string的二進制,而是加了點額外的信息,這在嚴格要求字節正確的場景下會出問題,如http請求體,服務器會對這些多出來的字節表示懵逼。前面多出來的字節實際上是表示string的長度,叫長度前綴(length-prefixed)MSDN,據SO某答主的說法,這是供BinaryReader的ReadString方法用,知道長度,它才知道要讀取到哪里。所以如果流的讀取方不是BinaryReader,這些長度前綴就是多余甚至是有害的,這種情況下就不能使用BinaryWriter.Write(string)方法。要想安全地獲取字符串的字節數據用UTF8Encoding的方式。