JavaScript 读取二进制文件的模拟方案

作者:半夏时间:2026-10-23 14:22:32浏览:627

JavaScript原生缺乏二进制处理能力,本文探讨利用XMLHTTP读取Unicode文本文件的特性,通过去除空字符0x0000并替换为低频字符Key,结合文件头记录位置信息,实现二进制数据的模拟读取与还原,适用于推箱子等游戏地图数据的存储场景。

JavaScript处理二进制数据的局限

浏览器内置的HTTP组件是否支持二进制数据流尚存争议,但JavaScript语言本身并不具备直接处理二进制数据的能力。有观点认为VBScript可以实现,因为VBScript、IE浏览器和ActiveX均为微软产品,三者结合紧密。IE的HTTP组件确实能读取二进制数据,但仅限于VBScript调用。对于其他浏览器,JavaScript处理二进制数据则显得力不从心。



脚本语言的设计初衷是处理简单的交互逻辑,处理字节流等复杂任务并非其职责所在。然而,作为一种技术探索,研究其可行性仍具趣味。虽然JavaScript无法直接读取二进制,但可以通过模拟手段达到类似效果,下文将详细介绍具体实现方法。



基于Unicode的模拟读取方案

以开发包含200关的推箱子游戏为例,核心难点在于地图数据的存储。若将所有关卡数据硬编码在脚本文件中,体积过大;若单独存储,则需确定文件格式。对于简单的推箱子游戏,文本格式或许足够;但对于复杂地图,常采用BASE64编码,由客户端HTTP组件下载并解码。BASE64编码在JavaScript中应用广泛,因其不受环境限制,仅需处理字符串即可。



既然存在BASE64,为何不能实现BASE128或BASE256?若能实现“BASE256”,即等同于处理二进制字节流。若此法可行,BASE64便不再流行。关键在于字符串与字节串的区别。尝试将二进制文件当作文本文件读取,会发现当文件中出现超过127(0x7F)的字符时立即报错;若存在0x00字节,后续内容将丢失。这意味着256个字符中可用者不足一半。



上述测试仅基于最基本的ASCII编码,而功能强大的XMLHTTP组件支持的范围更广。尝试读取保存为Unicode格式的文本文件,XMLHTTP显示的内容与记事本一致,但用16进制编辑器打开文件时,发现文件开头有FF FE两字节,后续内容均以0x00作为间隔。这是16位Unicode字符的特征,除基本ASCII外,还需保存各国文字。例如中文占用2字节,英文数字也占用2字节,高位由0填充(注意高位字节在低位字节之后)。


XMLHTTP能成功显示Unicode内容,说明其支持该编码。尝试修改文件数据以测试出错范围,将数据修改为:FFFE 0001 0203 7F00 8000 8100 FF00 FFFF。使用XMLHTTP测试,虽显示乱码但未报错,通过charCodeAt(i)及toString(16)方法验证,结果与原数据一致。经测试,Unicode不像ASCII有严格范围限制,但唯一例外是0x0000。


在ASCII中,0x00是结束标志;而在Unicode中,所有字符均为16位,因此字符尾也变为0x0000。目标明确:若能去除文件中的0x0000,并在文件头添加0xFEFF,即可让JavaScript成功读取。



编码解码策略与Key值应用

去除和恢复0x0000的过程可称为编码与解码。编码方法多样,最简单的是记录每个0x0000的位置并移除;客户端根据记录位置复原。虽然简单,但二进制文件中0x00及0x0000出现频率极高,仅记录位置会导致数据冗余。因此,应记录文件中出现次数最少的字符及其位置,将0x0000替换为该字符;解码时,若遇到该字符且位置不在记录中,则判定为0x0000。在64KB以下的文件中,必然存在未使用的字符(即使文件大于64KB,也有大量字符未使用)。Unicode字符多达65536个,除非是冗余极小的压缩文件,否则不会用尽所有字符。



编码与解码的思路已清晰,接下来是具体实现。


前文提到的源文件中出现最少(甚至未出现)的Unicode字符,此处称为Key。


二进制文件头格式定义

首先定义新生成的二进制文件头格式:


代码如下:

00 01 0xFEFF。 Unicode文件头,这是必须的
02 03 Key值。 为了不让0x0000成为Key,在寻找的过程中忽略0x0000
03 04 Key出现的次数+1。 +1是为了避免该位置出现0x0000,后面的也都一样
05 06
07 08 第1个Key的位置 用4字节保存每个Key的位置。
09 0A
0B 0C 。。。
0D 0E
0F 10 第n个Key的位置
11 12 文件数据内容。。。

1

2下一页阅读全文

作者最新文章