溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

varint是什么意思

發(fā)布時(shí)間:2021-12-09 15:28:27 來源:億速云 閱讀:232 作者:柒染 欄目:大數(shù)據(jù)

這篇文章給大家介紹varint是什么意思,內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對(duì)大家能有所幫助。

作為熟悉Kafka的讀者,肯定知道Kafka的消息中的很多長(zhǎng)度字段均采用了可變長(zhǎng)度的編碼格式,那么這種可變的編碼格式是什么呢,沒錯(cuò),就是我們今天要講的varint編碼格式。

字節(jié)序

計(jì)算機(jī)在信息傳輸?shù)倪^程中都是采用一定的編碼格式將數(shù)據(jù)編碼為二進(jìn)制,當(dāng)數(shù)據(jù)接收方收到數(shù)據(jù)以后也會(huì)進(jìn)行相應(yīng)的解碼將二進(jìn)制數(shù)據(jù)轉(zhuǎn)換成響應(yīng)的格式。在計(jì)算機(jī)中,一個(gè)二進(jìn)制數(shù)字(0或1)代表1Bit,8個(gè)Bit又稱為1個(gè)字節(jié)(byte)。

字節(jié)序指的就是多個(gè)字節(jié)在通信中的排列順序,字節(jié)序目前有兩種格式:

  • 大端序:整數(shù)的最高字節(jié)在存儲(chǔ)時(shí)在最低字節(jié)的前面則稱為大端序,通俗一點(diǎn)說就是按照數(shù)字的書寫順序進(jìn)行二進(jìn)制的轉(zhuǎn)換
  • 小端序:整數(shù)的最低字節(jié)在存儲(chǔ)時(shí)在最高字節(jié)的前面則稱為小端序,通俗一點(diǎn)說就是按照數(shù)字書寫的顛倒順序進(jìn)行二進(jìn)制的轉(zhuǎn)換

下圖就是數(shù)字123456的斷續(xù)和小端序的二進(jìn)制格式:

varint是什么意思  


首先int類型的數(shù)據(jù)占據(jù)4個(gè)字節(jié),以大端序?yàn)槔覀兛梢钥吹?23456的高位的第一個(gè)字節(jié)都是無用的,我們可以使用三個(gè)字節(jié)就能代表123456,由于Kafka的長(zhǎng)度字段的數(shù)值都會(huì)遠(yuǎn)遠(yuǎn)小于123456,甚至1個(gè)字節(jié)也可以表示,如果我們依舊使用int來表示長(zhǎng)度的話將會(huì)浪費(fèi)大量的空間,因此基于這個(gè)原因,Kafka在自己的v2消息格式中的長(zhǎng)度字段具采用了可變長(zhǎng)度的表示,這種表示方式就是通過varint編碼。

 
varint

varint其實(shí)并不僅僅在kafka中有所使用,大名鼎鼎的Protocol Buffers也使用varint編碼。

varint是使用一個(gè)或多個(gè)字節(jié)序列化整數(shù)的方式,他可以把一個(gè)固定字節(jié)的整數(shù)編碼成變長(zhǎng)字節(jié)。

varint編碼中每一個(gè)字節(jié)的最高位都不用來存儲(chǔ)數(shù)字的真正表示,而是表示當(dāng)前字節(jié)是否還屬于當(dāng)前數(shù)據(jù),1代表是,0代表不是(也就是該字節(jié)是當(dāng)前數(shù)據(jù)的最后一個(gè)字節(jié)數(shù)據(jù))。每一個(gè)字節(jié)的低7位用于以7位為一組存儲(chǔ)數(shù)字的二進(jìn)制補(bǔ)碼表示,最低有效數(shù)組在前,這也就表明varint編碼是按照小端序來排列的。

圖中對(duì)數(shù)字123456進(jìn)行varint編碼,123456用二進(jìn)制表示為1 11100010 01000000,每次低從向高取7位再加上最高有效位變成11000000 11000100 00000111。

varint是什么意思  


下面我們通過一段Java代碼實(shí)現(xiàn)varint編碼和解碼,其中只實(shí)現(xiàn)了無符號(hào)Interger類型的數(shù)據(jù)。

public class VarInt {
   public static void writeUnsignedVarint(int value, DataOutput output) throws IOException {        // value & 0xffffff80 當(dāng)前字節(jié)是否為最后一個(gè)字節(jié),不是則執(zhí)行while        while ((value & 0xffffff80) != 0) {            // value & 0x7f保證可以取到整數(shù)最低7位            // | 0x80 填充字節(jié)最高位為1,因?yàn)楫?dāng)前字節(jié)還不是數(shù)據(jù)的最后一個(gè)字節(jié)            byte b = (byte) ((value & 0x7f) | 0x80);            output.writeByte(b);            System.out.println(b);            value >>>= 7 ;        }        // 寫入最后一個(gè)字節(jié)        System.out.println(value);        output.writeByte(value);    }
   public static int readUnsignedVarint(ByteBuffer buffer) {        int value = 0;        int b;        int i = 0;        while (((b = buffer.get()) & 0x80) != 0) {            value |= (b & 0x7f) << i;            i += 7;            if (i >= 28) {                throw new IllegalArgumentException("illegal varint");            }        }        value |= b << i;        return value;    }
   public static void main(String[] args) throws IOException {        DataOutputStream output = new DataOutputStream(new ByteArrayOutputStream(2));        writeUnsignedVarint(123456, output);        System.out.println("encode size:" + output.size());        System.out.println("-----------");        byte[] bytes = new byte[]{-64, -60, 7};        ByteBuffer wrap = ByteBuffer.wrap(bytes);        System.out.println("decode:" + readUnsignedVarint(wrap));        System.out.println("-----------");    }}
關(guān)于varint是什么意思就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。
向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI