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。喜欢可以关注我噢~我有空了会分享做游戏的相关技术,会在这个专栏里分享:《教你做小游戏》。
标签:
为您推荐
广告
- JS 按自定义格式 拼接二进制串 解析二进制串
- 什琴斯尼:检查我都做了我没事,等不及想出场了
- 视讯!秦皇岛供电公司:开展世界读书日阅读分享活动
- 每日关注!拍卖房屋的税费由谁承担
- 山西985211大学有哪些_山西有哪些大学二本
- 资本金净利润率计算公式是什么_资本金净利润率-环球短讯
- 每日视点!贵州省民政厅免费发放2300份社工备考课包
- 1680个公办学位!深圳这区又一所九年一贯制学校将开建 天天观焦点
- 全国首创!青岛发布“硕果金”政策支持科技型中小微企业发展-报资讯
- SMM热卷日评:市场情绪低落 现货价格大幅下跌-信息
- 全球热点评!季后赛局势:76人横扫成晋级首队 湖人领衔五组2-1 太阳掘金获赛点
- 焦点热议:“五一”档电影预售即将破亿 17部新片参与角逐
- 斯奈德:特雷-杨会被对手格外关注 他要经历逆境-调整-提高的过程 动态焦点
- 天天动态:心理疗愈小锦囊丨“隐蔽型讨好”,也是一种内耗
- 微纪录片|平凡世界里的读书人
- 全球热门:只通过cfa一级可以拿到证书吗?考试要注意什么?
- dnf战法刷图加点_个人经验分享
- 每日速看!科普安卓手机内存清理方法及红米NOTE怎么打开USB调试
- 当前快播:重温文学经典 影视主创把《平凡的世界》读给你听
- 张家口市万全区:蔬菜种植忙
- 1淄博小饼遭疯抢老板暴瘦20斤 小葱等“灵魂搭配”也供不应求|环球即时
- 2焦点日报:维果斯基的最近发展区理论及其教学启示_维果斯基的最近发展区理论对儿童教育的启示是什么
- 3环球新资讯:无耻之徒第一季未删减版百度云_无耻之徒第一季未删减版
- 4超越影像,成就想象!OPPO超影像大赛开启,最高可获16万奖金_焦点快看
- 5今日看点:智能自控: 2023年一季度报告
- 6每日热议!为满足中国用户多样化需求,雷克萨斯LM有哪些“执念”
- 7资讯推荐:火火兔定时关机怎么关闭_火火兔定时关机在哪打开
- 8双喜临门 蒙玺投资荣膺金长江奖“快速成长私募基金公司”奖项-看点
- 9CCC证书到期了怎么办?
- 10城口仅6.2℃!重庆局地重返“初冬” 25日阳光重返气温回升 当前看点
- 1湖人首节领先26分追平季后赛纪录 首节灰熊落后湖人26分小托马斯这都是狄龙的错
- 2“五一”各地飞福建机票预订量同比增长超12倍 环球焦点
- 3世界短讯!鏉窞娴疯嫢鏈嶉グ鏈夐檺鍏徃_杭州海酷服饰有限公司
- 4世界观天下!推动基层内分泌学科发展 重庆市医师协会糖尿病专业委员会下基层活动到璧山
- 5全球视点!小学生爱祖国短篇诗歌大全_小学生爱祖国短篇诗歌
- 6【速看料】翻出厚衣服!气温倒退回3月甚至2月 什么时候能升温?雨雪何时停?
- 7收买被拐卖的儿童罪判刑规定
- 8河北确定14项重点任务巩固提升脱贫地区产业帮扶成效 天天时讯
- 9天天短讯!劳动合同分为哪几种 劳动合同包括什么 ?
- 10最新:“五一”假期国内游线上订单已基本追平2019年同期水平——旅游业复苏渐入佳境
广告
- 机场项目加紧推进_世界观点
- 市民建议家庭唯一住房买卖置换取消增值税和个税,上海市财政局回应|环球快消息
- 我国生态修复“负面清单”管控成效显著_快资讯
- 今日京剧猫白糖的真实身份视频_京剧猫白糖的真实身份:世界信息
- 天津教资考试时间安排(天津教资考试时间)
- 20个品种营收过亿 华北制药去年净利润负6.89亿元_每日精选
- 新消费时代下品牌面临数个痛点 直播电商是标配也是“助燃器”_当前看点
- 注意!一汽富维将于5月19日召开股东大会
- 方框内打钩符号怎么输入(方框内打钩符号怎么输入)_要闻
- 詹俊:拜仁换帅是不是正确决定?决赛会是皇马vsAC米兰吗?|热推荐
- 环球热点评!外媒:新冠疫情期间,美国监狱种族不平等现象进一步加深
- AI 海报引争议,到底谁在惶惶不安?-播报
- 全球快播:wwwbaidu.com 百度_www rrr80 com
- 国新B股(900913)4月21日游资资金净买入8624.00元-世界快消息
- can_can
- 自己染发怎么染才均匀_自己染发-今日讯
- 每日快看:广电网络股东户数减少339户,户均持股8.69万元
- 每日精选:清水源收年报问询函 被要求说明黄磷目前价格水平是否对公司盈利能力造成不利影响
- 微软Win12系统最低配置:内存要求增加到了 8GB
- 奥璞便携式养生炖盅,给你便捷的养生方式