【问题标题】:Variable length-encoding of int to 2 bytesint 到 2 个字节的可变长度编码
【发布时间】:2018-06-11 13:41:25
【问题描述】:

我正在实现可变长度编码并阅读 wikipedia 的相关信息。这是我发现的:

0x00000080  0x81 0x00

这意味着0x80 int 被编码为0x81 0x00 2 个字节。那是我无法理解的。好的,按照我们那里列出的算法。

  1. 二进制0x80:00000000 00000000 00000000 10000000
  2. 我们将符号位移动到下一个八位位组,因此我们拥有并设置为 1(表示我们有更多八位位组): 00000000 00000000 00000001 10000000 不等于 0x81 0x00。我试图为此编写一个程序:

    byte[] ba = new byte[]{(byte) 0x81, (byte) 0x00};
    int first = (ba[0] & 0xFF) & 0x7F;
    int second = ((ba[1] & 0xFF) & 0x7F) << 7;
    int result = first | second;
    System.out.println(result); //prints 1, not 0x80
    

ideone

我错过了什么?

【问题讨论】:

  • 我认为您错过了标题示例下的数字 137 示例。非常清楚。我不确定您为什么在步骤 2 中提到符号位,因为您的数字要么是无符号数,要么是正二进制补码数,因此不存在符号位问题。每个字节中都有一个 MSB(最高有效位),用于指示后面是否有另一个字节。每个字节编码原始数据的 7 位。
  • @ErwinBolwidt 但我使用这个例子将0x80 转换为可变长度编码。 0x80 = 10000000,最低 7 位 = 0000000 和有效字节 = 00000000。所以最终我们有 00000001 00000000 != 0x81 。真的不明白错误...
  • 你忘记了维基百科的第四个要点,最高位表示后面会跟着另一个字节:10000001 00000000
  • @MarkJeronimus Btw,this resource0x80 != 0x81 0x00...
  • 您的资源是 LSB 优先的,而 Wikipedia 示例是 MSB 优先的。有你的不同。只需将低位、中位和高位 7 位部分的顺序颠倒即可。

标签: java int byte primitive


【解决方案1】:

存在另一种整数的可变长度编码并被广泛使用。例如,1984 年的 ASN.1 将 define "length" field 设为:

长度的编码可以有两种形式:短或长。短的 form 是一个单字节,介于 0 和 127 之间。

长格式至少有两个字节长,第一个字节的第 8 位 字节设置为 1。第一个字节的位 7-1 表示还有多少字节 位于长度字段本身中。然后剩余的字节指定 长度本身,作为一个多字节整数。

此编码用于例如 DLMS COSEM 协议或 https 证书。简单代码可以看ASN.1 java library

【讨论】:

    【解决方案2】:

    让我们从维基百科页面回顾一下算法:

    1. 取整数的二进制表示
    2. 将其分成 7 位一组,值最高的组会少
    3. 将这七个位作为一个字节,将MSB(最高有效位)设置为1,除了最后一个;最后一个留 0

    我们可以这样实现算法:

    public static byte[] variableLengthInteger(int input) {
        // first find out how many bytes we need to represent the integer
        int numBytes = ((32 - Integer.numberOfLeadingZeros(input)) + 6) / 7;
        // if the integer is 0, we still need 1 byte
        numBytes = numBytes > 0 ? numBytes : 1;
        byte[] output = new byte[numBytes];
        // for each byte of output ...
        for(int i = 0; i < numBytes; i++) {
            // ... take the least significant 7 bits of input and set the MSB to 1 ...
            output[i] = (byte) ((input & 0b1111111) | 0b10000000);
            // ... shift the input right by 7 places, discarding the 7 bits we just used
            input >>= 7;
        }
        // finally reset the MSB on the last byte
        output[0] &= 0b01111111; 
        return output;
    }
    

    您可以从 Wikipedia 页面 here 看到它适用于示例,您也可以插入自己的值并在线尝试。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-03-17
      • 1970-01-01
      • 1970-01-01
      • 2013-07-09
      • 2016-05-09
      • 1970-01-01
      • 2011-04-03
      • 2019-06-26
      相关资源
      最近更新 更多