今日精选:JS 按自定义格式 拼接二进制串 解析二进制串
本文解答: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];}
decode难点
相比encode,decode其实是更难的事情。
因为encode时,你只需要无脑往一个字节串后面补充就好。而decode需要你非常清楚,每一位的作用,并理解他们的含义。你需要有高超的位运算技巧,才能轻易完成。
如何知道一共有多少项目
设计数据结构时,我们没有把项目数作为一个变量,所以数组长度是未知的。
也就是说,我们必须不断循环,直到这个字节串没有内容了,我们就终止。
如何读取制定长度bit位的内容
我们封装一个函数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。喜欢可以关注我噢~我有空了会分享做游戏的相关技术,会在这个专栏里分享:《教你做小游戏》。
标签:
精彩推送
环球快播:2023成都郫都区特殊需要儿童少年入学评估指南(对象+流程)
2023成都郫都区特殊需要儿童少年入学评估指南评估对象郫都区户籍范围内持残疾证适龄儿童少年;符合外来...
全球微资讯!警惕!正进行“航母化改装”的“加贺”号,1年来首次驶出船坞
【环球网报道】日本雅虎新闻平台20日刊发了英国《简氏防务周刊》的东京特派记者高桥浩祐的署名报道。报...
全球热点!jdg电子竞技俱乐部老板是谁-jdg电子竞技俱乐部老板
1、秦奋游戏ID风中追风,就是前两天上海撞坏红色法拉利那个,秦奋也有个King战队。2、王思聪有个IG战队秦...
最新灾害风险提示!湖北省西部和北部将出现“倒春寒”|环球百事通
最新灾害风险提示!湖北省西部和北部将出现“倒春寒”---湖北日报讯(记者胡雯洁、通讯员李伟)4月21日...
新闻快讯
X 关闭
X 关闭
新闻快讯
- 今日精选:JS 按自定义格式 拼接二进制串 解析二进制串
- 上游连年涨价,下游不许提价,燃气公司受不了了|当前快报
- 阿胶不融化是质量问题吗 世界最资讯
- 今日视点:魔芋果怎么做魔芋 魔芋果怎么吃
- “中国版IFRS17”提高会计质量,上市险企一季报首采新准则
- 下个月,你工资卡里或多一笔钱!-世界速看料
- 今日关注:1匹空调功率_是怎么计算的
- 沈楠2023年一季度表现,交银国企改革灵活配置混合A基金季度涨幅2.43%
- 百川论坛“第二届中国政治经济学理论与实践研讨会”在前海开幕_环球焦点
- 华中科技大学新闻与信息传播学院副院长郭小平:国内国际传播并重,让更多人行走河南、读懂中国 全球资讯
- 变压器kva怎样换算成电流_变压器kva换算kw
- 每日快报!某长颈鹿关于 「忠诚侍从 ~ Royal Retainer」的碎碎念
- pazz.zhangzhou.gov.cn_pazza inter-环球快播
- 配2.0T动力还有拉风套件 影豹R·ABT联名版亮相
- 当前最新:截至2022年底澳大利亚在建大型电池储能项目规模超过2GWh
- 萦绕指尖的书香,广州荔湾区举办了一场无障“爱”读书会
- 皆创历史!纽卡首次英超上半场进5+球,热刺首次英超上半场丢5+球-热点评
- 注意!黑客利用“明星塌房”大肆传播病毒
- 2023年04月23日股市盘中盘后重要消息
- 环球看点!淡季不淡 沪市基建类上市公司一季度业绩喜人
- 迈克特劳特身高体重_迈克特劳特
- 廉洁自律证明开具流程 廉洁自律证明
- 环球快消息!甲基异丁基甲醇商品报价动态(2023-04-23)
- 【环球播资讯】冤枉女孩偷文具店铺已关门停业
- B站两公司被爱奇艺起诉 案由均为侵权纠纷_世界球精选
- 【环球聚看点】尼克-杨发推:如果快船全员健康 他们将赢得总冠军
- 苹果手机照片无法同步微信_苹果手机照片无法同步
- Rookie开的餐厅倒闭,也搞差别对待,用过期拉面被投诉多次|环球短讯
- 热头条丨东西问·中外对话丨数字时代,我们为何还在读纸质书?
- 焦点!中消协发布“五一”假期消费提示:安全为先 绿色消费
- 大食国怎么读_大食国
- 环球视讯!椰子怎么吃?_椰子怎么吃图解
- 环球实时:消费股突然火了!8000字最新研判
- 世界速读:安徽萧县:关于萧县立亭合作社有关情况的通报
- 【全球聚看点】近95万升!美国加州洛杉矶县发生污水泄漏事件
- 汽车迎来保价潮,一季度价格战留下了哪些“后遗症”?
- 小鹏汽车1亿在武汉成立销售公司
- 要送8万名地球人去火星 马斯克:一切都是在推动世界向可持续的未来发展 速读
- 上海车展首发,易航智能推出单SOC行泊一体Lite方案
- 【今日杭州】枫映华庭明天登记,未来科技城红盘即将一把清
- 中国研制世界首台兆瓦级高温超导感应加热装置投用_观察
- 第六届太原图书馆读书节系列活动启动 天天关注
- 男子将房屋抵押银行贷款200万,银行因未实地调查,抵押权无效?|当前简讯
- 世界快资讯:实现户外用电自由,体验感拉满!铂陆帝户外电源新品重磅来袭
- 全球信息:外媒:美国今年群体凶杀事件或创纪录 几乎每星期一起
- 【世界新视野】京津冀晋联合开展"关爱河流 保护永定河"活动 弘扬植绿护绿爱绿文明新风
- 国乒提前锁定男单冠军!马龙4-1战胜法国新秀,王楚钦4-0张本智和
- 天天快看点丨女子一吃泡菜就头痛、看树干变弯:只因体内一种酶不足
- 提前154天!京港澳高速汉江特大桥完成升级改造恢复货车通行
- 跑跑车单机游戏下载(跑跑车单机游戏网官网)