代码之家  ›  专栏  ›  技术社区  ›  Some Name

int到2字节的可变长度编码

  •  1
  • Some Name  · 技术社区  · 7 年前

    我正在实现可变长度编码和读取 wikipedia 关于它。以下是我的发现:

    0x00000080  0x81 0x00
    

    它的意思是 0x80 int编码为 0x81 0x00 2字节。那是我无法理解的。好的,按照上面列出的算法。

    1. 二元的 0x80 : 00000000 00000000 00000000 10000000
    2. 我们将符号位移到下一个八位字节,这样我们就有并设置为1(表示我们有更多的八位字节): 00000000 00000000 00000001 10000000 不等于 0x81xx00 . 我试着写一个程序:

      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

    我错过了什么?

    1 回复  |  直到 7 年前
        1
  •  1
  •   O.O.Balance    7 年前

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

    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;
    }
    

    您可以看到它为维基百科页面上的示例工作。 here 你也可以插入你自己的价值观,并尝试在线。