您的位置:首頁(yè) >熱點(diǎn) > 正文

世界通訊!JS 按自定義格式 拼接二進(jìn)制串 解析二進(jìn)制串

本文解答:JS如何按自定義格式拼接二進(jìn)制串?如何解析二進(jìn)制串?

什么是二進(jìn)制串?

當你要存一些數據時(shí),可以用自定義格式存下來(lái),這樣最節約空間。


(資料圖片)

例如,你想存這些數據:

ID(范圍0-16)是否VIP(范圍0-1)星座(范圍0-11)年齡(范圍0-127)

那么你可以規定這種自定義格式的二進(jìn)制串:dddddddc cccbaaaa其中d c b a都是代表0或1,我們用最后4位(aaaa)表示“ID”,用b表示“是否VIP”,用ccc表示“星座”,用dddd表示年齡。

本來(lái)你可能會(huì )用uint32的數組來(lái)存這些,占4*32=128位,但是現在,我們只用了16位,2個(gè)uint8就存下了。非常節約存儲空間。這就是一種自定義格式的二進(jìn)制串。

注意:當今存儲確實(shí)不貴,但是如果你希望把信息存放到URL中,那么你的空間越小,URL就越短。這時(shí)候價(jià)值就非常大了。例如我之前開(kāi)發(fā)象棋小游戲,把棋局信息(包括當前棋盤(pán)狀態(tài)、所有回合操作記錄)都存到了URL中,就能非常方便的保存、分享游戲對局,方便大家復盤(pán)。詳見(jiàn)文章《保存象棋棋盤(pán)信息,需要多少比特?我只用139-167位二進(jìn)制》

在JS中,對應的數據類(lèi)型是Uint8Array。

拼接自定義格式二進(jìn)制串

function concatBits(current: number, offset: number, bits: number, bitsLength: number) {  let newCurrent = current;  let newOffset = offset;  const newUint8: number[] = [];  if (offset + bitsLength < 8) {    newCurrent |= bits << (8 - bitsLength - offset);    newOffset += bitsLength;  } else if (offset + bitsLength === 8) {    newUint8.push(current | bits);    newCurrent = 0;    newOffset = 0;  } else {    newCurrent |= bits >> (offset - 8 + bitsLength);    newUint8.push(newCurrent);    newCurrent = (bits << (16 - offset - bitsLength)) & 0xff;    newOffset = offset - 8 + bitsLength;  }  return [newCurrent, newOffset, newUint8];}

當然這還是有個(gè)限制:bitsLength必須小于等于8。如果超過(guò)8,可能一個(gè)bits要覆蓋3個(gè)uint8,這種情況沒(méi)考慮在內。

如果你需要拓展,歡迎繼續完善它!

解析自定義格式二進(jìn)制串

function readBits(array: Uint8Array, bitsOffset: number, bitsLength: number) {  const offset = bitsOffset % 8;  const index = Math.floor(bitsOffset / 8);  if ((offset + bitsLength > 8 && index + 1 >= array.length) || offset + bitsLength <= 8 && index >= array.length) {    throw new Error("readBitsError");  }  let number = offset + bitsLength <= 8 ? array[index] : (array[index] << 8) | array[index + 1];  const length = offset + bitsLength <= 8 ? 8 : 16;  number >>= (length - bitsLength - offset);  number &= ([0, 1, 3, 7, 15, 31, 63][bitsLength]);  return [number, bitsOffset + bitsLength];}

decode難點(diǎn)

相比encode,decode其實(shí)是更難的事情。

因為encode時(shí),你只需要無(wú)腦往一個(gè)字節串后面補充就好。而decode需要你非常清楚,每一位的作用,并理解他們的含義。你需要有高超的位運算技巧,才能輕易完成。

如何知道一共有多少項目

設計數據結構時(shí),我們沒(méi)有把項目數作為一個(gè)變量,所以數組長(cháng)度是未知的。

也就是說(shuō),我們必須不斷循環(huán),直到這個(gè)字節串沒(méi)有內容了,我們就終止。

如何讀取制定長(cháng)度bit位的內容

我們封裝一個(gè)函數readBits,用于讀取某個(gè)字節串,從第x位開(kāi)始、長(cháng)度為n的內容。

因此,需要3個(gè)參數:

字節串array位偏移量bitsOffset要讀取的長(cháng)度bitsLength

返回值主要是對應的內容(可以用一個(gè)uint8來(lái)表示),此外,讀取后還需要更新一下調用者的位偏移量bitsOffset,方便持續調用,所以我們順便把新的位偏移量bitsOffset返回,作為返回值第二項。

解釋

在本文場(chǎng)景下,要讀取的長(cháng)度bitsLength不超過(guò)8,所以我們要關(guān)注的數據量,只會(huì )來(lái)自1個(gè)uint8或者某連續2個(gè)uint8。

計算index就是為了判斷第一個(gè)關(guān)鍵的uint8的位置。

計算offset,知道應該從index的第幾位開(kāi)始算數。

然后通過(guò)比較offset + bitsLength8的大小,就知道我們需要關(guān)注1個(gè)uint8即可、還是需要關(guān)注連續2個(gè)uint8。

我們把需要關(guān)注的uint8賦值給number,用length表示我們關(guān)注8位還是16位。

例如number二進(jìn)制是10110000,我們需要取從2開(kāi)始的長(cháng)度為2的內容(即11)。該怎么做呢?

只需要把它右移4位(用于刪除不需要的后綴),再跟二進(jìn)制11做個(gè)與操作(用于刪除不需要的前綴),即可。

因此代碼會(huì )這樣寫(xiě):number >>= (length - bitsLength - offset);number &= ([0, 1, 3, 7, 15, 31, 63][bitsLength]);。

其中0 1 3 7 15 31 63,對應二進(jìn)制分別是0 1 11 111 1111 11111 111111。都是為了刪除前綴。

這里因為我需要的bitsLength有限,所以我用這種方式偷懶了。如果你要做的更通用,可能要這樣寫(xiě):2 ** bitsLength - 1,目的是獲取位長(cháng)度為bitsLength的全是1的數字,用于刪除number不需要的前綴。

readBits開(kāi)發(fā)完畢,以后可以這樣調用:

let current;let bitsOffset = 0;[current, bitsOffset] = readBits(array, bitsOffset, 4);

這會(huì )讀取字節串a(chǎn)rray的從第0位開(kāi)始、長(cháng)度為4個(gè)bit位的內容,賦值給current變量。

寫(xiě)在最后

我是HullQin,公眾號線(xiàn)下聚會(huì )游戲的作者(歡迎關(guān)注我,交個(gè)朋友)。轉發(fā)本文前需獲得作者HullQin授權。我獨立開(kāi)發(fā)了《聯(lián)機桌游合集》,是個(gè)網(wǎng)頁(yè),可以很方便的跟朋友聯(lián)機玩UNO、飛行棋、斗地主、五子棋、一夜狼、狼人殺、象棋、德國心臟病、達芬奇密碼等游戲,不收費無(wú)廣告。還開(kāi)發(fā)了《Dice Crush》參加Game Jam 2022。喜歡可以關(guān)注我噢~我有空了會(huì )分享做游戲的相關(guān)技術(shù),會(huì )在這個(gè)專(zhuān)欄里分享:《教你做小游戲》。

免責聲明:本文不構成任何商業(yè)建議,投資有風(fēng)險,選擇需謹慎!本站發(fā)布的圖文一切為分享交流,傳播正能量,此文不保證數據的準確性,內容僅供參考

關(guān)鍵詞:

相關(guān)內容

熱門(mén)資訊

国产福利萌白酱精品一区|国产成人久久精品流白浆|国产一级A级免费视频|久久综合亚洲鲁鲁五月天欧|欧美黑人巨大视频HD