web-dev-qa-db-fra.com

Décoder UTF-8 avec Javascript

J'ai JavaScript dans une page Web XHTML qui transmet des chaînes codées en UTF-8. Il doit continuer à adopter la version UTF-8 et à la décoder. Comment est-il possible de décoder une chaîne UTF-8 pour l'affichage?

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

Pour répondre à la question initiale: voici comment décoder utf-8 en javascript:

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

Plus précisément,

function encode_utf8(s) {
  return unescape(encodeURIComponent(s));
}

function decode_utf8(s) {
  return decodeURIComponent(escape(s));
}

Je viens de l'utiliser dans mon code, et cela fonctionne parfaitement.

97
CpnCrunch

Cela devrait fonctionner:

// http://www.onicos.com/staff/iz/amuse/javascript/expert/utf.txt

/* utf.js - UTF-8 <=> UTF-16 convertion
 *
 * Copyright (C) 1999 Masanao Izumo <[email protected]>
 * 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;
}

Découvrez la démo JSFiddle .

Voir également les questions connexes: ici et ici

17
Albert

La solution de @ albert était la plus proche, mais elle ne peut analyser que 3 caractères utf-8

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: []};
}

Ceci retourne {result: "parsed string", leftovers: [list of invalid bytes at the end]} si vous analysez la chaîne en morceaux.

EDIT: correction du problème trouvé par @unhammer.

6
fakedrake

Mettre à jour la réponse de @ Albert en ajoutant une condition pour 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;
}
5
lauthu

Voici une solution qui gère tous les points de code Unicode, y compris les valeurs supérieures (4 octets), et prise en charge par tous les navigateurs modernes (IE et autres> 5.5). Il utilise decodeURIComponent (), mais PAS les fonctions d'échappement/unescape déconseillées:

function utf8_to_str(a) {
    for(var i=0, s=''; i<a.length; i++) {
        var h = a[i].toString(16)
        if(h.length < 2) h = '0' + h
        s += '%' + h
    }
    return decodeURIComponent(s)
}

Testé et disponible sur GitHub

Pour créer UTF-8 à partir d'une chaîne:

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
}

Testé et disponible sur GitHub

5
Matthew Voss

Peut-être que l’utilisation de textDecoder sera suffisant.

Non pris en charge dans tous les navigateurs cependant. Mais cela pourrait suffire si vous utilisez un passage pour piétons ou tout autre cas d’utilisation pour lequel vous savez quel navigateur est utilisé.

var decoder = new TextDecoder('utf-8'),
    decodedMessage;

decodedMessage = decoder.decode(message.data);
2
Jonathan

// String to 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 en chaîne

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

Je pense que le moyen le plus simple serait d’utiliser une fonction js intégrée, decodeURI ()/encodeURI ().

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

En utilisant mon 1.6KB bibliothèque , vous pouvez faire

ToString(FromUTF8(Array.from(usernameReceived)))
0
MCCCS

C’est ce que j’ai trouvé après une recherche Google plus spécifique que le codage/décodage UTF-8. Donc, pour ceux qui recherchent une bibliothèque de conversion pour convertir entre les encodages, c'est parti.

https://github.com/inexorabletash/text-encoding

var uint8array = new TextEncoder().encode(str);
var str = new TextDecoder(encoding).decode(uint8array);

Coller depuis le repo readme

Tous les encodages de la spécification Encoding sont supportés:

utf-8 ibm866 iso-8859-2 iso-8859-3 iso-8859-4 iso-8859-5 iso-8859-6 iso-8859-7 iso-8859-8 iso-8859-8-i iso-8859- 10 iso-8859-13 iso-8859-14 iso-8859-15 iso-8859-16 koi8-r koi8-u fenêtres Macintosh-874 fenêtres-1250 fenêtres-1251 fenêtres-1252 fenêtres-1253 fenêtres-1254 fenêtres-1254 fenêtres -1256 fenêtres-1257 fenêtres-1258 x-mac-cyrillic gb18030 hz-gb-2312 big5 euc-jp iso-2022-jp shift_jis remplacement euc-kr utf-16be utf-16le x défini par l'utilisateur

(Certains codages peuvent être pris en charge sous d'autres noms, par exemple ascii, iso-8859-1, etc. Voir Codage pour des étiquettes supplémentaires pour chaque codage.)

0
Olle Tiinus