HTML5文件API读取为文本和二进制文件

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

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

readAsBinaryString表示数据必须表示为二进制string ,其中:

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

JavaScript原本没有“二进制”types(直到ECMAScript 5支持Typed Array * (详见下文) – 它已经被ECMAScript 2015的ArrayBuffer所取代),所以他们用一个String来保证没有存储字符在string中会超出范围0..255。 (他们本来可以用一组数字来代替,但是它们没有;可能大string比大数字数组更有内存效率,因为数字是浮点数。

如果你正在阅读的文件大部分是西方脚本中的文本(例如大部分是英文),那么这个string看起来很像文本。 如果你阅读一个带有Unicode字符的文件,你应该注意到一个区别,因为JavaScriptstring是UTF-16 ** (下面详细介绍) ,所以一些字符的值将高于255,而根据文件的“二进制string” API规范不会有超过255的任何值(你将有两个单独的“字符”的Unicode码位的两个字节)。

如果你正在阅读的文件根本不是文本(也许是图片),你可能仍然会在readAsTextreadAsBinaryString之间得到一个非常相似的结果,但是对于readAsBinaryString知道不会有任何解释多字节序列作为字符。 您不知道如果您使用readAsText ,因为readAsText将使用编码确定来试图找出文件的编码,然后将其映射到JavaScript的UTF-16string。

如果您创build文件并将其存储在ASCII或UTF-8以外的其他文件中,您可以看到效果。 (在Windows中,你可以通过记事本来做到这一点;“另存为”作为一个编码下拉与“Unicode”,通过它看起来数据,他们似乎意味着UTF-16;我确定Mac OS和* nix编辑器也有类似的function。)下面是一个转储两种文件读取结果的页面:

 <!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> 

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

 文本(13):

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

二进制(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 

正如你所看到的, readAsText解释了字符,所以我得到了13(“testing1 2 3”的长度), readAsBinaryString没有,所以我得到了28(两字节的BOM加上每个字符两个字节) 。


responseType = "arraybuffer"支持XMLHttpRequest.response和responseType = "arraybuffer"

** “JavaScriptstring是UTF-16”可能看起来像一个奇怪的声明; 他们不只是Unicode吗? 不,JavaScriptstring是一系列UTF-16编码单元 ; 您将代理对看作两个单独的JavaScript“字符”,即使实际上代理对整体只是一个字符。 详情请参阅链接。

我想你可以使用readAsArrayBuffer()来获取二进制数据。