javascript - read - HTML5 File API leer como texto y binario
manejo de archivos en javascript (2)
Creo que puedes usar readAsArrayBuffer() para obtener datos binarios.
Actualmente estoy trabajando en la API de archivos HTML5 y necesito obtener datos de archivos binarios. The FileReader
de readAsText
y readAsDataURL
funcionan bien, pero readAsBinaryString
devuelve los mismos datos que readAsText
.
Necesito datos binarios, pero estoy obteniendo una cadena de texto. ¿Me estoy perdiendo de algo?
readAsBinaryString
dice que los datos se deben representar como una cadena binaria , donde:
... cada byte está representado por un entero en el rango [0..255].
JavaScript originalmente no tenía un tipo "binario" (hasta que WebGL de ECMAScript 5 admite Typed Array * (detalles a continuación) - ha sido reemplazado por ECMAScript 2015''s ArrayBuffer ) y por lo tanto se fueron con una cadena con la garantía de que ningún carácter almacenado en el String estaría fuera del rango 0..255. (Podrían haber ido con una matriz de números en su lugar, pero no lo hicieron, tal vez las cadenas grandes son más eficientes en cuanto a la memoria que las grandes matrices de números, ya que los números son de coma flotante).
Si está leyendo un archivo que en su mayoría es texto en una secuencia de comandos occidental (principalmente inglés, por ejemplo), esa cadena se parecerá mucho al texto. Si lee un archivo con caracteres Unicode, debería notar una diferencia, ya que las cadenas de JavaScript son UTF-16 ** (detalles a continuación) y, por lo tanto, algunos caracteres tendrán valores superiores a 255, mientras que una "cadena binaria" según el Archivo La especificación API no tendría ningún valor superior a 255 (tendría dos "caracteres" individuales para los dos bytes del punto de código Unicode).
Si estás leyendo un archivo que no es texto en absoluto (una imagen, tal vez), probablemente aún obtendrás un resultado muy similar entre readAsText
y readAsBinaryString
, pero con readAsBinaryString
sabes que no habrá ningún intento de interpretar múltiples -byte secuencias como personajes. No lo sabe si usa readAsText
, porque readAsText
usará una determinación de codificación para tratar de descubrir cuál es la codificación del archivo y luego asignarlo a las cadenas UTF-16 de JavaScript.
Puede ver el efecto si crea un archivo y lo almacena en algo que no sea ASCII o UTF-8. (En Windows puede hacer esto a través del Bloc de notas, el "Guardar como" como un menú desplegable de codificación con "Unicode", por lo que al mirar los datos parecen significar UTF-16; estoy seguro de que Mac OS y * Los editores nix tienen una función similar). Aquí hay una página que arroja el resultado de leer un archivo en ambos sentidos:
<!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>
Si uso eso con un archivo "Testing 1 2 3" almacenado en UTF-16, estos son los resultados que obtengo:
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
Como puede ver, readAsText
interpretó los caracteres y obtuve 13 (la longitud de "Testing 1 2 3"), y readAsBinaryString
no, y obtuve 28 (la UTF-16 dos bytes más dos bytes para cada carácter) .
* XMLHttpRequest.response con responseType = "arraybuffer"
es compatible con HTML 5.
** "Las cadenas de JavaScript son UTF-16" puede parecer una declaración extraña; ¿no son solo Unicode? No, una cadena de JavaScript es una serie de unidades de código UTF-16 ; usted ve los pares sustituto como dos "personajes" de JavaScript individuales, aunque, de hecho, el par suplente en su conjunto es solo un personaje. Ver el enlace para más detalles.