今天偶然发现一个问题——字符串字节获取的方式不同会导致获取的结果不一样。
定义如下方法,用于获取字符串的字节:
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的方式。
感谢这位老哥的文章