2010-06-30 16 views
24

Actualmente estoy trabajando en el API de archivos HTML 5, y necesito para obtener datos de archivos binarios. The FileReader 's readAsText y readAsDataURL métodos funcionan bien, pero readAsBinaryString devuelve los mismos datos que readAsText.API HTML5 de lectura de archivo como texto y binarios

Necesito datos binarios, pero Im consiguiendo una cadena de texto. ¿Me estoy perdiendo de algo?

Respuesta

66

readAsBinaryString dice que los datos deben ser representados como una binary string, donde:

... cada byte es representado por un número entero en el intervalo [0..255].

JavaScript originalmente no tenía un tipo "binario" (hasta que el soporte WebGL de ECMAScript 5 de Typed Array * (detalles a continuación) - ha sido reemplazado por ECMAScript 2015 de ArrayBuffer) y por lo que se fue con una cadena con la garantía de que ningún personaje almacenado en la Cadena estaría fuera del rango 0..255. (Podrían haber ido con una matriz de números en su lugar, pero no lo hicieron; quizás las cadenas grandes sean 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 archivo que en su mayoría es texto en una secuencia de comandos occidental (principalmente inglés, por ejemplo), entonces esa cadena se verá como un lote como texto. Si se lee un archivo con caracteres Unicode en él, usted debe notar una diferencia, ya que son cadenas JavaScript UTF-16** (detalles a continuación) y por lo que algunos caracteres tendrán valores por encima de 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á leyendo un archivo que no es texto en absoluto (una imagen, tal vez), es probable que aún así obtener un resultado muy similar entre readAsText y readAsBinaryString, pero con readAsBinaryString que saben que no habrá ser cualquier intento de interpretar secuencias de múltiples bytes como caracteres. ¿No sabe que si se utiliza readAsText, porque readAsText usará un encoding determination para tratar de averiguar lo que la codificación del archivo es y luego asignarla a UTF-16 cuerdas de JavaScript.

se puede ver el efecto si se 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 * editores nix tienen una característica similar) aquí hay una página que vuelca el resultado de la lectura de un archivo de dos maneras:.

<!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 utilizo que con un archivo "Prueba 1 2 3" almacenado en UTF-16, aquí están los resultados que obtienen:

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 se puede ver, readAsText interpretaron los personajes y por lo que tiene 13 (la longitud de "Prueba 1 2 3"), y readAsBinaryString no, y por lo que consiguieron 28 (el bytede dos bytesmás dos bytes para cada personaje).


* XMLHttpRequest.response con responseType = "arraybuffer" se apoya en 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 a series of UTF-16 code units; 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.

+0

¿Devuelve el texto codificado de 0 a 255? ¿Hay alguna forma de convertir esos caracteres a datos binarios o hexadecimales (0-1 o 0-FF)? – tcooc

+1

@digitalFresh: La cadena * es * la información binaria. Mientras comentábamos, publiqué un ejemplo que puede ser útil. JavaScript no tiene un tipo "binario", por lo que fueron con una cadena con la garantía de que ningún carácter almacenado en la cadena estaría fuera del rango 0..255. (Podrían haber ido con una matriz de números, pero no lo hicieron). El ejemplo muestra cómo obtener el valor bruto de un "carácter" de la cadena. –

+0

He intentado este código con Chrome 7.0. La devolución de llamada nunca se llama. Al mismo tiempo, no hay errores en la ventana de depuración. ¿Alguna ayuda? – morpheus

Cuestiones relacionadas