我正在研究解析器以接收UDP信息,解析它并存储它。为此,我使用的是BinaryReader
,因为它主要是二进制信息。其中一些将是字符串。 ReadString()
函数的MSDN says:
从当前流中读取字符串。字符串以前缀为前缀 长度,一次编码为整数7位。
我完全理解它,直到“一次七位”,我试图忽略,直到我开始测试。我在创建自己的字节数组之前将其放入MemoryStream
并尝试使用BinaryReader
进行读取。这是我最初认为可行的方法:
byte[] data = new byte[] { 3, 0, 0, 0, (byte)'C', (byte)'a', (byte)'t', }
BinaryReader reader = new BinaryReader(new MemoryStream(data));
String str = reader.ReadString();
知道一个int
是4个字节(并且足够长的时间来发现BinaryReader
是Little Endian)我将它的长度传递给3和相应的字母。但是str
最终会占据\0\0\0
。如果我删除3个零并且只有
byte[] data = new byte[] { 3, (byte)'C', (byte)'a', (byte)'t', }
然后它正确地读取和存储Cat
。对我来说,这与文档冲突说长度应该是一个整数。现在我开始认为它们只是指一个没有小数位且不是数据类型int
的数字。这是否意味着BinaryReader
永远不会读取大于127个字符的字符串(因为这将是对应于文档的7位部分的01111111)?
我正在编写一个协议,需要在将文档传递给客户之前完全理解我正在进行的工作。
答案 0 :(得分:6)
我找到BinaryReader
的{{3}}。它使用了一个名为source code的函数,在查找了Read7BitEncodedInt()的文档和文档后,我发现了这个:
值参数的整数在a处写出7位 时间,从七个最低有效位开始。高位 一个字节表示此后是否有更多字节要写入 一。如果value适合7位,则只需要一个字节的空间。 如果值不适合7位,则在第1位设置高位 字节并写出来。然后将值移位7位,然后移位 字节写入。重复此过程,直到整数整数为止 写了。
此外,拉尔夫发现Write7BitEncodedInt()可以更好地显示正在发生的事情。
答案 1 :(得分:0)
除非他们专门说'int'或'Int32',否则它们只是表示整数。
“一次7位”表示它们实现7位长度的编码,乍一看似乎有些混乱,但实际上相当简单。以下是一些示例值,以及如何使用7位长度编码将其写出:
/*
decimal value binary value -> enc byte 1 enc byte 2 enc byte 3
85 00000000 00000000 01010101 -> 01010101 n/a n/a
1,365 00000000 00000101 01010101 -> 11010101 00001010 n/a
349,525 00000101 01010101 01010101 -> 11010101 10101010 00010101
*/
上面的表使用大字节序,除了我只需要选择一个,这就是我最熟悉的原因。 7位长度编码的工作方式,就其本质而言,它几乎没有尾数。
请注意,85写入1字节,1,365写入2字节,349,525写入3字节。
在同一张表中使用字母显示写入输出中每个值的位是如何使用的(破折号是零值位,而0和1是编码机制添加的值,以指示是否要使用后续字节书面/阅读)...
/*
decimal value binary value -> enc byte 1 enc byte 2 enc byte 3
85 -------- -------- -AAAAAAA -> 0AAAAAAA n/a n/a
1,365 -------- -----BBB AAAAAAAA -> 1AAAAAAA 0---BBBA n/a
349,525 -----CCC BBBBBBBB AAAAAAAA -> 1AAAAAAA 1BBBBBBA 0--CCCBB
*/
因此,0到2 ^ 7-1(127)范围内的值将写为1个字节,2 ^ 7(128)到2 ^ 14-1(16,383)范围内的值将使用2个字节,即2 ^ 14(16,384)到2 ^ 21-1(2,097,151)将占用3个字节,依此类推。