varint:int数字用变长字节数组表示。
package com.ls.hfvj;
import java.util.Arrays;
/**
* varint:把整数用变长字节数组表示,每个int用1-5个byte表示。一个字节内,低7位是有效数据位,第8位是标识位,1表示有后续字节,0则表示该整数的结束没有后续字节。
* 当整数是小正数时,得到的字节序列明显比较小一些。
* 编码:每次取7位,或上符号位。
* 解码:每次从一个字节中取低7位进行位或
* @author lihao
*/
public class VarintEncode {
/**
* 对一个整数进行varint编码,返回编码后的字节序列 一个字节有8位,用最高位表示下一个字节是否连续
*/
public static byte[] encode(int val) {
byte[] data = new byte[computeLength(val)];
for (int i = 0; i < data.length - 1; i++) {
data[i] = (byte) ((val & 0x7F) | 0x80);// 用位或运行填上一个高位1,大类型向小类型强转只保留低位,高位丢失
val = val >>> 7;
}
data[data.length - 1] = (byte) (val);
return data;
}
/**
* 从一个整数的varint序列还原该数 4*7=28,若有5个字节,则第五个字节只有后4位是属于原数字的;//notice
*/
public static int decode0(byte[] data) {
int val = 0;
int i = data.length - 1;
if (data.length == 5) {
val = val | (data[i] & 0x0F);// 只要后四位
i -= 1;
}
while (i >= 0) {
val = val << 7;
val = val | (data[i] & 0x7F);
i--;
}
return val;
}
/**
* 把int转为varint编码需要的字节数 ,每次无符号右移7位,直到为0。返回值为1-5
*/
public static int computeLength(int val) {
if (val == 0) {
return 1;
}
int length = 0;
while (val != 0) {
val = val >>> 7;
length++;
}
return length;
}
public static void main(String[] args) {
byte[] data = encode(300);
System.out.println(Arrays.toString(data));
System.out.println(decode0(data));
}
}