protobuf varint编解码实现

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

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值