我目前正在研究 HTML5 文件 API,我需要获取二进制文件数据。
The FileReader
的readAsText
和readAsDataURL
方法工作正常,但readAsBinaryString
返回与 相同的数据readAsText
。
我需要二进制数据,但我得到了一个文本字符串。我错过了什么吗?
我目前正在研究 HTML5 文件 API,我需要获取二进制文件数据。
The FileReader
的readAsText
和readAsDataURL
方法工作正常,但readAsBinaryString
返回与 相同的数据readAsText
。
我需要二进制数据,但我得到了一个文本字符串。我错过了什么吗?
2018 年的注意事项:readAsBinaryString
已过时。对于您以前使用过的用例,现在您将使用readAsArrayBuffer
(或在某些情况下,readAsDataURL
)代替。
readAsBinaryString
表示数据必须表示为二进制字符串,其中:
...每个字节都由 [0..255] 范围内的整数表示。
JavaScript 最初没有“二进制”类型(直到 ECMAScript 5 的 WebGL 支持Typed Array * (详细信息如下) ——它已被 ECMAScript 2015 的ArrayBuffer取代),因此它们使用 String 并保证不存储任何字符在字符串中将超出范围 0..255。(他们本来可以使用数字数组代替,但他们没有;也许大字符串比大数字数组更节省内存,因为数字是浮点数。)
如果你正在读这主要是在西部的脚本文本(主要是英语,例如)的文件,那么该字符串看起来会很多像文本。如果您读取一个包含 Unicode 字符的文件,您应该会注意到一个不同之处,因为 JavaScript 字符串是UTF-16 ** (详情如下),因此某些字符的值会高于 255,而根据 File 的“二进制字符串” API 规范不会有任何大于 255 的值(对于 Unicode 代码点的两个字节,您将有两个单独的“字符”)。
如果您正在阅读一个根本不是文本的文件(也许是图像),您可能仍然会在readAsText
和之间获得非常相似的结果readAsBinaryString
,但是readAsBinaryString
您知道不会尝试解释多字节序列作为字符。你不知道如果你使用readAsText
, 因为readAsText
将使用编码确定来尝试找出文件的编码是什么,然后将它映射到 JavaScript 的 UTF-16 字符串。
如果您创建一个文件并将其存储在 ASCII 或 UTF-8 以外的其他格式中,您可以看到效果。(在 Windows 中,您可以通过记事本执行此操作;“另存为”作为带有“Unicode”的编码下拉列表,通过查看数据,它们似乎意味着 UTF-16;我确定 Mac OS 和 * nix 编辑器有一个类似的功能。)这是一个页面,它转储两种方式读取文件的结果:
<!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 中的“Testing 1 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(“测试 1 2 3”的长度),readAsBinaryString
但没有,所以我得到了 28(两字节BOM加上每个字符的两个字节)。
* XMLHttpRequest.response withresponseType = "arraybuffer"
在 HTML 5 中受支持。
** “JavaScript 字符串是 UTF-16”可能看起来很奇怪;他们不只是Unicode吗?不,JavaScript 字符串是一系列 UTF-16 代码单元;您将代理对视为两个单独的 JavaScript“字符”,尽管实际上,代理对作为一个整体只是一个字符。有关详细信息,请参阅链接。