HTML5文件API读作文本和二进制文件

时间:2010-06-30 04:28:53

标签: javascript html file html5

我目前正在研究HTML5文件API,我需要获取二进制文件数据。 The FileReader readAsTextreadAsDataURL方法工作正常,但readAsBinaryString返回与readAsText相同的数据。

我需要二进制数据,但我得到一个文本字符串。我错过了什么吗?

1 个答案:

答案 0 :(得分:72)

2018年注意readAsBinaryString已过时。对于以前使用过它的用例,这些天您使用的是readAsArrayBuffer(或者在某些情况下,readAsDataURL)。


readAsBinaryString表示数据必须表示为binary string,其中:

  

...每个字节由[0..255]范围内的整数表示。

JavaScript最初没有“二进制”类型(直到ECMAScript 5对Typed Array * 的WebGL支持(详情如下) - 它已被ECMAScript 2015 {{3}取代因此,他们使用String并保证String中存储的字符不在0..255范围之外。 (他们本可以使用一组数字代替,但他们没有;也许大字符串比大数字数组更有内存效率,因为数字是浮点数。)

如果您正在阅读一个主要是西方文字文本的文件(例如,大部分是英文),那么该字符串将看起来像文本一样 lot 。如果您读取其中包含Unicode字符的文件,您应该注意到一个区别,因为JavaScript字符串是ArrayBuffer ** (详情如下),因此某些字符的值大于255,而根据File API规范的“二进制字符串”不会有任何高于255的值(对于Unicode代码点的两个字节,你有两个单独的“字符”)。

如果你正在阅读一个完全不是文本的文件(可能是一个图像),你可能在readAsTextreadAsBinaryString之间得到一个非常相似的结果,但{{1}您知道不会尝试将多字节序列解释为字符。如果您使用readAsBinaryString,则不知道,因为readAsText将使用UTF-16来确定文件的编码是什么,然后将其映射到JavaScript的UTF-16字符串。

如果您创建文件并将其存储为ASCII或UTF-8以外的其他内容,则可以看到效果。 (在Windows中,您可以通过记事本执行此操作;将“另存为”作为带有“Unicode”的编码下拉列表,通过该下拉列表查看它们似乎意味着UTF-16的数据;我确定Mac OS和* nix编辑器具有类似的功能。)这是一个转储文件读取结果的页面:

readAsText

如果我使用UTF-16中存储的“Testing 1 2 3”文件,我得到的结果如下:

Text (13):

54 65 73 74 69 6e 67 20 31 20 32 20 33

Binary (28):

ff fe 54 00 65 00 73 00 74 00 69 00 6e 00 67 00 20 00 31 00 20 00 32 00 20 00 33 00

正如你所看到的,<!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-type" content="text/html;charset=UTF-8"> <title>Show File Data</title> <style type='text/css'> body { font-family: sans-serif; } </style> <script type='text/javascript'> function loadFile() { var input, file, fr; if (typeof window.FileReader !== 'function') { bodyAppend("p", "The file API isn't supported on this browser yet."); return; } input = document.getElementById('fileinput'); if (!input) { bodyAppend("p", "Um, couldn't find the fileinput element."); } else if (!input.files) { bodyAppend("p", "This browser doesn't seem to support the `files` property of file inputs."); } else if (!input.files[0]) { bodyAppend("p", "Please select a file before clicking 'Load'"); } else { file = input.files[0]; fr = new FileReader(); fr.onload = receivedText; fr.readAsText(file); } function receivedText() { showResult(fr, "Text"); fr = new FileReader(); fr.onload = receivedBinary; fr.readAsBinaryString(file); } function receivedBinary() { showResult(fr, "Binary"); } } function showResult(fr, label) { var markup, result, n, aByte, byteStr; markup = []; result = fr.result; for (n = 0; n < result.length; ++n) { aByte = result.charCodeAt(n); byteStr = aByte.toString(16); if (byteStr.length < 2) { byteStr = "0" + byteStr; } markup.push(byteStr); } bodyAppend("p", label + " (" + result.length + "):"); bodyAppend("pre", markup.join(" ")); } function bodyAppend(tagName, innerHTML) { var elm; elm = document.createElement(tagName); elm.innerHTML = innerHTML; document.body.appendChild(elm); } </script> </head> <body> <form action='#' onsubmit="return false;"> <input type='file' id='fileinput'> <input type='button' id='btnLoad' value='Load' onclick='loadFile();'> </form> </body> </html> 解释了角色,所以我得到13(“测试1 2 3”的长度),readAsText没有,所以我得到28(双字节encoding determination加上每个字符的两个字节。)


HTML 5支持带有readAsBinaryString的{​​p> * BOM

** “JavaScript字符串是UTF-16”似乎是一个奇怪的陈述;他们不只是Unicode吗?不,JavaScript字符串是XMLHttpRequest.response;你将代理对看作两个单独的JavaScript“字符”,尽管事实上,代理对作为一个整体只是一个字符。有关详细信息,请参阅链接。