本文解答:JS如何按自定义格式拼接二进制串?如何解析二进制串?
(资料图)
当你要存一些数据时,可以用自定义格式存下来,这样最节约空间。
例如,你想存这些数据:
ID(范围0-16)是否VIP(范围0-1)星座(范围0-11)年龄(范围0-127)那么你可以规定这种自定义格式的二进制串:dddddddc cccbaaaa
其中d c b a都是代表0或1,我们用最后4位(aaaa)表示“ID”,用b表示“是否VIP”,用ccc表示“星座”,用dddd表示年龄。
本来你可能会用uint32的数组来存这些,占4*32=128位,但是现在,我们只用了16位,2个uint8就存下了。非常节约存储空间。这就是一种自定义格式的二进制串。
注意:当今存储确实不贵,但是如果你希望把信息存放到URL中,那么你的空间越小,URL就越短。这时候价值就非常大了。例如我之前开发象棋小游戏,把棋局信息(包括当前棋盘状态、所有回合操作记录)都存到了URL中,就能非常方便的保存、分享游戏对局,方便大家复盘。详见文章《保存象棋棋盘信息,需要多少比特?我只用139-167位二进制》
在JS中,对应的数据类型是Uint8Array。
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];}
当然这还是有个限制:bitsLength必须小于等于8。如果超过8,可能一个bits要覆盖3个uint8,这种情况没考虑在内。
如果你需要拓展,欢迎继续完善它!
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];}
相比encode,decode其实是更难的事情。
因为encode时,你只需要无脑往一个字节串后面补充就好。而decode需要你非常清楚,每一位的作用,并理解他们的含义。你需要有高超的位运算技巧,才能轻易完成。
设计数据结构时,我们没有把项目数作为一个变量,所以数组长度是未知的。
也就是说,我们必须不断循环,直到这个字节串没有内容了,我们就终止。
我们封装一个函数readBits
,用于读取某个字节串,从第x位开始、长度为n的内容。
因此,需要3个参数:
字节串array
位偏移量bitsOffset
要读取的长度bitsLength
返回值主要是对应的内容(可以用一个uint8来表示),此外,读取后还需要更新一下调用者的位偏移量bitsOffset
,方便持续调用,所以我们顺便把新的位偏移量bitsOffset
返回,作为返回值第二项。
解释
在本文场景下,要读取的长度bitsLength
不超过8,所以我们要关注的数据量,只会来自1个uint8或者某连续2个uint8。
计算index
就是为了判断第一个关键的uint8的位置。
计算offset
,知道应该从index
的第几位开始算数。
然后通过比较offset + bitsLength
和8
的大小,就知道我们需要关注1个uint8即可、还是需要关注连续2个uint8。
我们把需要关注的uint8赋值给number
,用length
表示我们关注8位还是16位。
例如number二进制是10110000
,我们需要取从2开始的长度为2的内容(即11
)。该怎么做呢?
只需要把它右移4位(用于删除不需要的后缀),再跟二进制11
做个与操作(用于删除不需要的前缀),即可。
因此代码会这样写:number >>= (length - bitsLength - offset);
number &= ([0, 1, 3, 7, 15, 31, 63][bitsLength]);
。
其中0 1 3 7 15 31 63,对应二进制分别是0 1 11 111 1111 11111 111111。都是为了删除前缀。
这里因为我需要的bitsLength有限,所以我用这种方式偷懒了。如果你要做的更通用,可能要这样写:2 ** bitsLength - 1
,目的是获取位长度为bitsLength的全是1的数字,用于删除number不需要的前缀。
readBits
开发完毕,以后可以这样调用:
let current;let bitsOffset = 0;[current, bitsOffset] = readBits(array, bitsOffset, 4);
这会读取字节串array的从第0位开始、长度为4个bit位的内容,赋值给current变量。
我是HullQin,公众号线下聚会游戏的作者(欢迎关注我,交个朋友)。转发本文前需获得作者HullQin授权。我独立开发了《联机桌游合集》,是个网页,可以很方便的跟朋友联机玩UNO、飞行棋、斗地主、五子棋、一夜狼、狼人杀、象棋、德国心脏病、达芬奇密码等游戏,不收费无广告。还开发了《Dice Crush》参加Game Jam 2022。喜欢可以关注我噢~我有空了会分享做游戏的相关技术,会在这个专栏里分享:《教你做小游戏》。
下一篇:最后一页
那么你可以规定这种自定义格式的二进制串:dddddddccccbaaaa其中dcba都是代表0或1,我们用最后4位(aaaa)
以下是一个使用Channel的示例程序,该程序创建了两个Goroutine,并使用Channel在它们之间进行通信和同步。
情系环山旅游公路(一)
1、直到世界末日(电视剧华集)宋:王赢演唱:安迪桃花满枝。2、它在落下之前开花。3、让赞美沉醉在这杯酒里
1、如果你是广西用户,你可以登录http: gx 12530 com。2、输入你的手机号和密码,点击验证码右上角的‘我
智通财经APP讯,世纪恒通(301428 SZ)披露招股意向书,该公司拟首次公开发行2466 6667万股,且不低于发行后
1、释义:闲适貌;淡泊貌。2、叶圣陶《游临潼》:“荷池里只剩荷梗了,几只鸭悠然浮在池面。3、”2、以...
1、英[ˈaɪvəri]美[ˈaɪvəri,ˈaɪvri]n 象牙;象牙色;象牙制品;象牙质adj 象牙色的
◎实习记者都芃“万老师,EAST实现了403秒的H模等离子体运行!”“祝贺!祝贺!大家辛苦了!”4月20日,...
1、注意作息时间。2、如果阴天下雨潮湿加重麻木,人们要做好保暖防潮。本文到此结束,希望对大家有所帮助。
1、歌词:2、害怕被拒绝3、害怕被遗漏4、你害怕被命运妥协吗?5、当真爱被宣布缺乏时。6、新专辑宣传照7、
“一季度,我区商品房销售面积同期增长60%。”4月23日,大东区政府副区长吴迪在接受沈阳日报、沈报全媒...
耿马傣族佤族自治县气象台发布雷电预警信号黄色预警【Ⅲ级 较重】【2023-04-24】
镇康县气象台发布雷电预警信号黄色预警【Ⅲ级 较重】【2023-04-24】
截止2023年一季度末,基金经理杜沛管理的国泰景气行业灵活配置混合(003593)季度净值涨4 04%。
2023光遇4月23日每日任务介绍分享给大家,可能不少网友对这个还不太了解,而自己去慢慢探索也需要花费不少
相约安徽,向春而行│“世界地球日”用鸟语花香唤醒每一天,与西湖湿地一同守护众生的地球!
【走进基层看作风】记者探访铜川政务大厅,三心服务让人心暖
请问,宝贝我爱你英语怎样写很多人还不知道,现在让我们一起来看看吧!1、Honey,Iloveyou!!!这才是地道的美
蜂蜜怎样祛斑,蜂蜜祛斑的方法很多人还不知道,现在让我们一起来看看吧!解答:1、蜂蜜可以用来调理色斑。
受访专家:首都医科大学附属北京佑安医院呼吸与感染性疾病科主任医师李侗曾西安交通大学第二附属医院感染科
1、先了解老人需要什么。2、需要什么买什么老人开心!2、投其所好。3、每个人的爱好不一样,即使类似的东西
1、虎鲸是一种大型齿鲸,身长为8~10米,体重9吨左右,背呈黑色,腹为灰白色,有一个尖尖的背鳍,背鳍弯曲
1、女主人公伊莎贝尔侨居英国时先后拒绝了两个青年的求婚,从爱着她的表兄拉尔夫那里得到了他父亲的7万镑遗
一、建设工程款怎么算利息建设工程款算利息方式:当事人对欠付工程价款利息计付标准有约定的,按照约定处理
广告
X 关闭
广告
X 关闭