C#
'sBinaryReader
有一个函数,根据 MSDN,读取编码为“七位整数”的整数,然后读取具有该整数长度的字符串。
是否有关于七位整数格式的明确文档(我粗略了解 MSB 或 LSB 标记是否有更多字节要读取,其余位是数据,但我会很高兴更准确的)。
更好的是,是否有一种C
以这种格式读写数字的实现?
C#
'sBinaryReader
有一个函数,根据 MSDN,读取编码为“七位整数”的整数,然后读取具有该整数长度的字符串。
是否有关于七位整数格式的明确文档(我粗略了解 MSB 或 LSB 标记是否有更多字节要读取,其余位是数据,但我会很高兴更准确的)。
更好的是,是否有一种C
以这种格式读写数字的实现?
好吧,BinaryReader.Read7BitEncodedInt的文档已经说过,它希望使用BinaryWriter.Write7BitEncodedInt写入值,并且该方法文档详细说明了格式:
value 参数的整数一次写入 7 位,从 7 个最低有效位开始。一个字节的高位表示在这个字节之后是否还有更多字节要写入。
如果值适合七位,则只占用一个字节的空间。如果值不适合七位,则在第一个字节上设置高位并写出。然后将值移动七位并写入下一个字节。重复这个过程,直到整个整数都被写入。
所以整数 1259551277,二进制 1001011000100110011101000101101 将被转换为 7 位格式,如下所示:
Remaining integer encoded bytes
1001011000100110011101000101101
100101100010011001110100 00101101
10010110001001100 10101101 01110100
1001011000 10101101 11110100 01001100
100 10101101 11110100 11001100 01011000
0 10101101 11110100 11001100 11011000 00000100
不过,我现在对自己的 C 语言技能并没有那么有信心提供一个可行的实现。但根据那个描述,这并不是很难做到。
基本上,7 位编码背后的想法Int32
是减少小值所需的字节数。它是这样工作的:
Int32.MaxValue
从每个字节中仅窃取 1 位,也不需要超过 5 个字节)。如果第 5 个字节的最高位仍然设置,则您读取的内容不是 7 位编码的 Int32。请注意,由于它是逐字节写入的,因此对于这些值而言,字节顺序根本不重要。对于给定的值范围,需要以下字节数:
Int32.MaxValue
) 和 -2,147,483,648 ( Int32.MinValue
) 到 -1正如你所看到的,实现有点愚蠢,负值总是需要 5 个字节,因为符号位是原始值的第 32 位,总是在第 5 个字节结束。
因此,我不建议将它用于负值或大于 ~250,000,000 的值。我只看到它在内部用于 .NET 字符串的字符串长度前缀(您可以使用BinaryReader.ReadString
and读取/写入的字符串BinaryReader.WriteString
),描述字符串所包含的字符数,只有正值。
虽然您可以查找原始 .NET 源代码,但我在BinaryData 库中使用了不同的实现。
我还必须探索这种 7 位格式。在我的一个项目中,我使用 C# 的 BinaryWriter 将一些数据打包到文件中,然后使用 BinaryReader 再次解压,效果很好。
后来我还需要为这个项目的 Java 打包文件实现一个阅读器。Java 有一个名为 DataInputStream 的类(在 java.io 包中),它有一些类似的方法。不幸的是,DataInputStream 的数据解释与 C# 非常不同。
为了解决我的问题,我自己通过编写一个扩展 java.io.DataInputStream 的类将 C# 的 BinaryReader 移植到 Java。这是我写的方法,它和 C# 的 BinaryReader.readString() 完全一样:
public String csReadString() throws IOException {
int stringLength = 0;
boolean stringLengthParsed = false;
int step = 0;
while(!stringLengthParsed) {
byte part = csReadByte();
stringLengthParsed = (((int)part >> 7) == 0);
int partCutter = part & 127;
part = (byte)partCutter;
int toAdd = (int)part << (step*7);
stringLength += toAdd;
step++;
}
char[] chars = new char[stringLength];
for(int i = 0; i < stringLength; i++) {
chars[i] = csReadChar();
}
return new String(chars);
}
/*
* Parameters: plOutput[out] - The decoded integer
* pbyInput[in] - Buffer containing encoded integer
* Returns: Number of bytes used to encode the integer
*/
int SevenBitEncodingToInteger(int *plOutput, char *pbyInput)
{
int lSize = 0;
int lTemp = 0;
while(true)
{
lTemp += pbyInput[lSize] & 0x7F;
if(pbyInput[lSize++] > 127)
lTemp <<= 7;
else
break;
}
*plOutput = lTemp;
return lSize;
}
Write7BitEncodedInt 方法包含描述:每个字节的最低 7 位编码数字的下 7 位。当后面有另一个字节时,最高位被设置。