5

我正在开发一个解析器来接收 UDP 信息,解析它并存储它。为此,我使用 aBinaryReader因为它主要是二进制信息。不过,其中一些将是字符串。MSDNReadString()功能说:

从当前流中读取一个字符串。该字符串以长度为前缀,一次编码为一个整数七位。

我完全理解它,直到“一次七位”,我试图简单地忽略它,直到我开始测试。我正在创建自己的字节数组,然后将其放入 aMemoryStream并尝试使用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();

知道 anint是 4 个字节(并且玩弄了足够长的时间以找出它BinaryReader是 Little Endian)我将它传递给 3 的长度和相应的字母。然而str最终持有\0\0\0。如果我删除 3 个零并且只有

byte[] data = new byte[] { 3, (byte)'C', (byte)'a', (byte)'t', }

然后它会Cat正确读取和存储。对我来说,这与文档说长度应该是整数相冲突。现在我开始认为它们只是表示没有小数位的数字而不是数据类型int。这是否意味着 aBinaryReader永远无法读取大于 127 个字符的字符串(因为 01111111 对应于文档的 7 位部分)?

我正在编写一个协议,并且需要在将我们的文档传递给我们的客户之前完全了解我所涉及的内容。

4

2 回答 2

7

找到BinaryReader. 它使用一个名为Read7BitEncodedInt()的函数,在查找该文档和Write7BitEncodedInt()的文档后,我发现了这个:

value 参数的整数一次写入 7 位,从 7 个最低有效位开始。一个字节的高位表示在这个字节之后是否还有更多字节要写入。如果值适合七位,则只占用一个字节的空间。如果值不适合七位,则在第一个字节上设置高位并写出。然后将值移动七位并写入下一个字节。重复这个过程,直到整个整数都被写入。

此外,Ralf 发现这个链接可以更好地显示正在发生的事情。

于 2013-10-31T16:04:56.923 回答
2

除非他们特别说“int”或“Int32”,否则它们只是表示整数中的整数。

'7 bits at time' 表示它实现了 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 个字节,依此类推。

于 2020-05-26T04:30:58.423 回答