MQTT-Java 可变字节整数-Variable Byte Integer

161 阅读2分钟

目标

理解可变字节整数概念,即MQTT5.0 协议中的 “1.5.5 Variable Byte Integer”内容

介绍

MQTT中的“可变字节整数”其实是可变字节编码算法,用于对整数序列进行快速压缩。
在英文表达中常见的写法有:Variable byte codes,Variable-Byte Codes,Variable Encoding,Variable byte, varints

具体编解码算法实现,可具体参见“1.5.5 Variable Byte Integer”中的样例内容

相关文章

根据MQTT规范实践算法

实践数字序列

125,128,16385,2097152

实践日志

2023-09-01 15:52:07:718 编码前的数字序列为:125 128 16385 2097152 
2023-09-01 15:52:07:718 编码后二进制: 1111101 10000000 1 10000001 10000000 1 10000000 10000000 10000000 1 
2023-09-01 15:52:07:718 解码后的数字序列为:125 128 16385 2097152 

Java算法代码

package com.harvey.mqtt;

import org.eclipse.paho.mqttv5.client.logging.HarveyDebug;

import java.io.ByteArrayOutputStream;

/**
 *
 * MQTT5.0 : https://docs.oasis-open.org/mqtt/mqtt/v5.0/mqtt-v5.0.pdf
 * 参见 "1.5.5 Variable Byte Integer" 内容
 *
 */
public class ExampleVariableByteInteger {

    public static void main(String[] args) {

        ByteArrayOutputStream bais = new ByteArrayOutputStream();

        int [] inNum = {125, 128, 16385, 2097152};
        int x = 16385;

        StringBuilder sbInNum = new StringBuilder();
        sbInNum.append("编码前的数字序列为:");
        StringBuilder sb = new StringBuilder();

        for (int k : inNum){
            x = k;
            sbInNum.append(x).append(" ");

            do{
                int encodeByte = x % 128;
                x = x / 128;

                if ( x > 0){
                    encodeByte = (encodeByte | 128);
                }
                bais.write(encodeByte);

                sb.append(Integer.toBinaryString(encodeByte)).append(" ");
            } while ( x > 0);

        }

        HarveyDebug.d(sbInNum.toString());
        HarveyDebug.d("编码后二进制: " + sb.toString());

        HarveyDebug.d();

        StringBuilder sbDecodeNum = new StringBuilder();
        sbDecodeNum.append("解码后的数字序列为:");

        byte [] covert = bais.toByteArray();
        int index = 0;

        do{
            int multiplier = 1;
            int value = 0;
            int encodedByte = 0;
            do{
                encodedByte = covert[index];
                value += (encodedByte & 127) * multiplier;

                if(multiplier > 128*128*128){
                    System.err.println("非法编码");
                    break;
                }
                multiplier *= 128;
                index++;
            } while ((encodedByte & 128) != 0);

            sbDecodeNum.append(value).append(" ");

        } while (index < covert.length);

        HarveyDebug.d(sbDecodeNum.toString());
    }

}