之前以為BinaryWriter寫string會嚴格按構造時指定的編碼(不指定則是無BOM的UTF8)寫入string的二進位,如下麵的代碼: 因為字母a的utf8編碼是97,所以我預期data只有1個元素且值為97,而實際上,data有兩個元素,依次為1、97,顯然97代表a,但前面的1是什麼鬼, ...
之前以為BinaryWriter寫string會嚴格按構造時指定的編碼(不指定則是無BOM的UTF8)寫入string的二進位,如下麵的代碼:
//將字元串"a"寫入流,再拿到流的位元組組data using (var ms = new MemoryStream()) { using (var bw = new BinaryWriter(ms)) { bw.Write("a"); } byte[] data = ms.ToArray(); }
因為字母a的utf8編碼是97,所以我預期data只有1個元素且值為97,而實際上,data有兩個元素,依次為1、97,顯然97代表a,但前面的1是什麼鬼,再試其它字元串,仍然會在前面多出1個甚至多個位元組,值也比較漂浮,總之就是bw並沒有原原本本的寫入string的二進位,而是加了些料,這在嚴格要求位元組正確的場景會出問題,如http請求體,伺服器會對這些多出來的位元組表示懵逼。遂搜索一番,發現MSDN、stackoverflow早有提到,前面多出來的位元組實際上是表示string的長度,叫長度首碼(length-prefixed),據SO某答主的說法,這是供BinaryReader的ReadString方法用,知道長度,它才知道要讀取到哪裡。所以如果流的讀取方不是BinaryReader,這些長度首碼就是多餘甚至是有害的,這種情況下就不能使用BinaryWriter.Write(string)方法,要寫入乾凈的string二進位,可以這樣:
bw.Write(Encoding.UTF8.GetBytes("a"));//按需選用正確的編碼
即先用具體編碼得到string的位元組組,再用BinaryWriter.Write(byte[])寫入該位元組組。
-文畢-