Decodificar o UTF-8 com Javascript

Eu tenho o Javascript em uma página web XHTML que está passando cadeias codificadas UTF-8. Ele precisa continuar a passar a versão UTF-8, bem como decodificá-lo. Como é possível decodificar uma string UTF-8 para exibição?

 // <![CDATA[ function updateUser(usernameSent){ var usernameReceived = usernameSent; // Current value: Größe var usernameDecoded = usernameReceived; // Decode to: Größe var html2id = ''; html2id += 'Encoded: ' + usernameReceived + '
Decoded: ' + usernameDecoded; document.getElementById('userId').innerHTML = html2id; } // ]]>

    Para responder a pergunta original: aqui está como você decodifica o utf-8 em javascript:

    http://ecmanaut.blogspot.ca/2006/07/encoding-decoding-utf8-in-javascript.html

    Especificamente,

     function encode_utf8(s) { return unescape(encodeURIComponent(s)); } function decode_utf8(s) { return decodeURIComponent(escape(s)); } 

    Eu usei isso no meu código e funciona perfeitamente.

    Isso deve funcionar:

     // http://www.onicos.com/staff/iz/amuse/javascript/expert/utf.txt /* utf.js - UTF-8 <=> UTF-16 convertion * * Copyright (C) 1999 Masanao Izumo  * Version: 1.0 * LastModified: Dec 25 1999 * This library is free. You can redistribute it and/or modify it. */ function Utf8ArrayToStr(array) { var out, i, len, c; var char2, char3; out = ""; len = array.length; i = 0; while(i < len) { c = array[i++]; switch(c >> 4) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: // 0xxxxxxx out += String.fromCharCode(c); break; case 12: case 13: // 110x xxxx 10xx xxxx char2 = array[i++]; out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F)); break; case 14: // 1110 xxxx 10xx xxxx 10xx xxxx char2 = array[i++]; char3 = array[i++]; out += String.fromCharCode(((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0)); break; } } return out; } 

    Confira a demonstração do JSFiddle .

    Veja também as perguntas relacionadas: aqui e aqui

    @ solução de albert foi o mais próximo que eu acho, mas só pode analisar até 3 byte utf-8 caracteres

     function utf8ArrayToStr(array) { var out, i, len, c; var char2, char3; out = ""; len = array.length; i = 0; // XXX: Invalid bytes are ignored while(i < len) { c = array[i++]; if (c >> 7 == 0) { // 0xxx xxxx out += String.fromCharCode(c); continue; } // Invalid starting byte if (c >> 6 == 0x02) { continue; } // #### MULTIBYTE #### // How many bytes left for thus character? var extraLength = null; if (c >> 5 == 0x06) { extraLength = 1; } else if (c >> 4 == 0x0e) { extraLength = 2; } else if (c >> 3 == 0x1e) { extraLength = 3; } else if (c >> 2 == 0x3e) { extraLength = 4; } else if (c >> 1 == 0x7e) { extraLength = 5; } else { continue; } // Do we have enough bytes in our data? if (i+extraLength > len) { var leftovers = array.slice(i-1); // If there is an invalid byte in the leftovers we might want to // continue from there. for (; i < len; i++) if (array[i] >> 6 != 0x02) break; if (i != len) continue; // All leftover bytes are valid. return {result: out, leftovers: leftovers}; } // Remove the UTF-8 prefix from the char (res) var mask = (1 << (8 - extraLength - 1)) - 1, res = c & mask, nextChar, count; for (count = 0; count < extraLength; count++) { nextChar = array[i++]; // Is the char valid multibyte part? if (nextChar >> 6 != 0x02) {break;}; res = (res << 6) | (nextChar & 0x3f); } if (count != extraLength) { i--; continue; } if (res <= 0xffff) { out += String.fromCharCode(res); continue; } res -= 0x10000; var high = ((res >> 10) & 0x3ff) + 0xd800, low = (res & 0x3ff) + 0xdc00; out += String.fromCharCode(high, low); } return {result: out, leftovers: []}; } 

    Isso retorna {result: "parsed string", leftovers: [list of invalid bytes at the end]} caso você esteja analisando a string em pedaços.

    EDIT: corrigido o problema que @unhammer encontrado.

    Aqui está uma solução que manipula todos os pontos de código Unicode incluem valores superiores (4 bytes) e suportados por todos os navegadores modernos (IE e outros> 5.5). Ele usa decodeURIComponent (), mas NÃO as funções de escape / unescape obsoletas:

     function utf8_to_str(a) { for(var i=0, s=''; i 

    Testado e disponível no GitHub

    Para criar o UTF-8 a partir de uma string:

     function utf8_from_str(s) { for(var i=0, enc = encodeURIComponent(s), a = []; i < enc.length;) { if(enc[i] === '%') { a.push(parseInt(enc.substr(i+1, 2), 16)) i += 3 } else { a.push(enc.charCodeAt(i++)) } } return a } 

    Testado e disponível no GitHub

    Atualize a resposta de @ Albert adicionando condição para emoji.

     function Utf8ArrayToStr(array) { var out, i, len, c; var char2, char3, char4; out = ""; len = array.length; i = 0; while(i < len) { c = array[i++]; switch(c >> 4) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: // 0xxxxxxx out += String.fromCharCode(c); break; case 12: case 13: // 110x xxxx 10xx xxxx char2 = array[i++]; out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F)); break; case 14: // 1110 xxxx 10xx xxxx 10xx xxxx char2 = array[i++]; char3 = array[i++]; out += String.fromCharCode(((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0)); break; case 15: // 1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx char2 = array[i++]; char3 = array[i++]; char4 = array[i++]; out += String.fromCodePoint(((c & 0x07) << 18) | ((char2 & 0x3F) << 12) | ((char3 & 0x3F) << 6) | (char4 & 0x3F)); break; } return out; } 

    Talvez o uso do textDecoder seja suficiente.

    Não suportado em todos os navegadores. Mas pode ser suficiente usar crosswalk ou qualquer outro caso de uso em que você saiba qual navegador é usado.

     var decoder = new TextDecoder('utf-8'), decodedMessage; decodedMessage = decoder.decode(message.data); 

    Eu acho que a maneira mais fácil seria usar um built-in funções js decodeURI () / encodeURI ().

     function (usernameSent) { var usernameEncoded = usernameSent; // Current value: utf8 var usernameDecoded = decodeURI(usernameReceived); // Decoded // do stuff } 

    // String para Utf8 ByteBuffer

     function strToUTF8(str){ return Uint8Array.from(encodeURIComponent(str).replace(/%(..)/g,(m,v)=>{return String.fromCodePoint(parseInt(v,16))}), c=>c.codePointAt(0)) } 

    // Utf8 ByteArray para string

     function UTF8toStr(ba){ return decodeURIComponent(ba.reduce((p,c)=>{return p+'%'+c.toString(16),''})) } 

    Eu procurei por uma solução simples e isso funciona bem para mim:

     //input data view = new Uint8Array(data); //output string serialString = ua2text(view); //convert UTF8 to string function ua2text(ua) { s = ""; for (var i = 0; i < ua.length; i++) { s += String.fromCharCode(ua[i]); } return s; } 

    O único problema que tenho é que às vezes recebo um caractere de cada vez. Isso pode ser por design com a minha fonte do arraybuffer. Estou usando https://github.com/xseignard/cordovarduino para ler dados seriais em um dispositivo Android.