用html书写的文件是二进制文件( ),用JavaScript读写二进制文件的另一种方法

曾经写过一篇《用JavaScript读写二进制文件》,其实严格的说是JScript,但是很多不明真相的同学根本不区分。内容摘自CodeProject《Reading and Writing Binary Files Using JScript》一文。最近要用JScript处理一些二进制的*.torrent文件,重新看了一遍原文,发现有人在回复中提供了一种更简洁的方法

《a shorter and quicker way [modified]》,英文好的同学自己看原文,我为英文不好的同学简单翻译一下,虽然我英文也很烂。

我一直在寻找怎样在WSH中利用JScript处理二进制文件,这是我找到的最好的方法但是我很快就意识到你可以使用1252代码页(Demon注:详见《ISO-8859-1和Windows-1252的区别》),这不需要庞大的映射,并且经过一番睡觉之后(Demon注:原文是after sleeping on it,实在不知道怎么翻译了o(╯□╰)o),我意识到把读到的字符一个一个映射是非常繁琐和缓慢的。于是我原封不动的保留读取的字符串,但把它封装成一个拥有映射方法的字符串对象,像这样:

// When we read a binary stream as ISO 8859-1 (Latin 1), we should get a string

// 当我们用ISO 8859-1 (Latin 1)编码读取二进制流的时候,我们将得到一个字符串,

// where each charCodeAt value matches the byte from the stream. Unfortunately

// 每个字符的charCodeAt值都对应二进制流的一个字节。遗憾的是

// Windows won't give you Latin 1 -- when you ask for it, you get code page

// Windows并不给你Latin 1 —— 当你请求它的时候,你得到的是代码页

// 1252, which has extra characters stuck in for byte values from 128 to 159.

// 1252,它含有额外的字符,会影响从128到159的字节的值

// These two strings allow us to translate between the bogus Windows characters

// 这两个字符串允许我们完成虚假的Windows字符和原始字节值之间的转换

// and the original byte values.

varbogusWindows1252chars ="\u20AC\u201A\u0192\u201E\u2026\u2020\u2021"+

"\u02C6\u2030\u0160\u2039\u0152\u017D"+

"\u2018\u2019\u201C\u201D\u2022\u2013\u2014"+

"\u02DC\u2122\u0161\u203A\u0153\u017E\u0178";

// No translation is necessary for characters 0x81, 0x8D, 0x8F, 0x90, or 0x9D.

// 0x81, 0x8D, 0x8F, 0x90, or 0x9D的字符不需要转换

varcorrectLatin1chars ="\u0080\u0082\u0083\u0084\u0085\u0086\u0087"+

"\u0088\u0089\u008A\u008B\u008C\u008E"+

"\u0091\u0092\u0093\u0094\u0095\u0096\u0097"+

"\u0098\u0099\u009A\u009B\u009C\u009E\u009F";

// This turns a string read as codepage 1252 into a boxed string with a

// 返回一个以1252代码页读取的字符串,并封装了byteAt方法

// byteAt method. We also modify the slice method to return a similar object.

// 我们也修改了slice方法使之返回一个相同的对象

functionbinaryString(str)

{

varr = str ?newString(str) :newString();

// always return an object with a .length

// 总是返回一个含有 .length属性的对象

r.byteAt =function(index)

{

// translate character back to originating Windows-1252 byte value

// 把Windows-1252字节转换成原始字节值

if(this.charCodeAt(index) <=255)

return this.charCodeAt(index);

varp = bogusWindows1252chars.indexOf(this.charAt(index));

returncorrectLatin1Chars.charCodeAt(p);

};

r.slice =function(start, end)

{

returnbinaryString(this.substring(start, end));

};

returnr;

}

// Does reverse translation from bytes back to Windows-1252 characters. You can

// 完成相反的从原始值向Windows-1252字符的转换

// build up a string to write back to disk by concatenating a bunch of these.

// 你可以建立一个写回硬盘的字符串,以连接的方法

functionfromByte(num)

{

varc =String.fromCharCode(num);

varp = correctLatin1chars.indexOf(c);

returnp >=0? bogusWindows1252chars.charAt(p) : c;

}

// Reads bytes from a file, returning them as a binaryString.

// 读取文件的字节,以二进制字符串的形式返回它们

functionbinaryReadFile(path, maxLength)

{

varbinstream =newActiveXObject("ADODB.Stream");

binstream.Type =2/*adTypeText 文本模式 */;

binstream.Charset ="iso-8859-1";// actually Windows codepage 1252 其实是Windows-1252

binstream.Open();

binstream.LoadFromFile(path);

returnbinaryString(binstream.ReadText(maxLength));

}

我仅仅实现二进制读取,而没有实现二进制写入,但是结合上下文,这是很简单的。你可能想把 fromByte 函数拓展成为一个能够转换较大的块的方法,比如像产生大端序或者 UTF-8 的字符串的方法,或者任何你想要的格式,这样你就不需要每次都一个一个地连接字节。

这样比原来短了很多,不是吗?也许还会更快,至少你不用多次处理同一字节。在我使用的某些地方,它确实比较快,比如读取MP3文件并提取一些它们的ID3标签。在这个情况下,你只需要用indexOf来寻找标签,这样只有很少的字符需要转换成字节。

如果需要更大的读写,可以把映射缓存到数组中。这样 byteAt 和 fromByte 就会变得很短并且很快。你仅仅需要初始化一个循环来操作它们,从bogusWindows1252chars到correctLatin1chars字符串。

翻译得很烂,有个别语句我自己都没看懂。在这里纠正一下原作者的错误, ADODB.Stream很BUG,当你用iso-8859-1字符集读取文本的时候,跟上面说的一样,Windows不会给你iso-8859-1(无视标准是微软的一贯作风),而是用Windows-1252字符集(两者的区别详见《ISO-8859-1和Windows-1252的区别》)。所以得到的字符串的charCodeAt值与原二进制流并不一一对应,需要将Windows-1252额外的字符做一个映射。但是,如果你用iso-8859-1写入文本,这时的的确确是iso-8859-1,Windows不会再当成Windows-1252。所以,读取的字符串并不需要再次转回Windows-1252,原作者写错了。

随机文章:

这篇文章发布于 2011年04月21日,星期四,23:22,归类于 程序设计。您可以跟踪这篇文章的评论通过 RSS 2.0 feed。

您可以留下评论,或者从您的站点trackback。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值