Conversión más sencilla de ArrayBuffer a string con la API de codificación

Hace más de dos años, Renato Mangini describió un método para convertir entre ArrayBuffers sin procesar y la representación de cadena correspondiente de esos datos. Al final de la publicación, Renato mencionó que se estaba redactando una API oficial estandarizada para controlar la conversión. La especificación ya está madura, y tanto Firefox como Google Chrome agregaron compatibilidad nativa con las interfaces TextDecoder y TextEncoder.

Como se muestra en este ejemplo en vivo, que se extrae a continuación, la API de Encoding facilita la traducción entre bytes sin procesar y cadenas nativas de JavaScript, independientemente de con cuál de las muchas codificaciones estándar debas trabajar.

<pre id="results"></pre>

<script>
    if ('TextDecoder' in window) {
    // The local files to be fetched, mapped to the encoding that they're using.
    var filesToEncoding = {
        'utf8.bin': 'utf-8',
        'utf16le.bin': 'utf-16le',
        'macintosh.bin': 'macintosh'
    };

    Object.keys(filesToEncoding).forEach(function(file) {
        fetchAndDecode(file, filesToEncoding[file]);
    });
    } else {
    document.querySelector('#results').textContent = 'Your browser does not support the Encoding API.'
    }

    // Use XHR to fetch `file` and interpret its contents as being encoded with `encoding`.
    function fetchAndDecode(file, encoding) {
    var xhr = new XMLHttpRequest();
    xhr.open('GET', file);
    // Using 'arraybuffer' as the responseType ensures that the raw data is returned,
    // rather than letting XMLHttpRequest decode the data first.
    xhr.responseType = 'arraybuffer';
    xhr.onload = function() {
        if (this.status == 200) {
        // The decode() method takes a DataView as a parameter, which is a wrapper on top of the ArrayBuffer.
        var dataView = new DataView(this.response);
        // The TextDecoder interface is documented at http://encoding.spec.whatwg.org/#interface-textdecoder
        var decoder = new TextDecoder(encoding);
        var decodedString = decoder.decode(dataView);
        // Add the decoded file's text to the <pre> element on the page.
        document.querySelector('#results').textContent += decodedString + '\n';
        } else {
        console.error('Error while requesting', file, this);
        }
    };
    xhr.send();
    }
</script>

En el ejemplo anterior, se usa la detección de funciones para determinar si la interfaz TextDecoder requerida está disponible en el navegador actual y, si no es así, se muestra un mensaje de error. En una aplicación real, lo normal es que recurras a una implementación alternativa si no hay compatibilidad nativa. Por fortuna, la biblioteca de codificación de texto que Renato mencionó en su artículo original sigue siendo una buena opción. La biblioteca usa los métodos nativos en los navegadores que los admiten y ofrece polyfills para la API de Encoding en los navegadores que aún no agregaron compatibilidad.

Actualización de septiembre de 2014: Se modificó el ejemplo para ilustrar cómo verificar si la API de Encoding está disponible en el navegador actual.