Connaître la longueur UTF-8 d'une chaîne JavaScript
Le
Olivier Miakinen

[diapublication avec f.c.n.unicode, suivi dans f.c.l.javascript seul]
Bonjour,
En JavaScript, les chaînes de caractères sont représentées en interne
dans le charset UTF-16, et c'est lors des interactions avec l'extérieur
(par exemple une requête AJAX ou XMLHttpRequest) qu'elles sont traduites
en UTF-8.
Je voudrais, dans JavaScript, savoir quelle sera la longueur d'une
chaîne en nombre d'octets une fois traduite en UTF-8. Je sais que la
propriété 'length' ne donne pas la bonne valeur (c'est le nombre de
seizets UTF-16). Comment puis-je faire ?
Cordialement,
--
Olivier Miakinen
Bonjour,
En JavaScript, les chaînes de caractères sont représentées en interne
dans le charset UTF-16, et c'est lors des interactions avec l'extérieur
(par exemple une requête AJAX ou XMLHttpRequest) qu'elles sont traduites
en UTF-8.
Je voudrais, dans JavaScript, savoir quelle sera la longueur d'une
chaîne en nombre d'octets une fois traduite en UTF-8. Je sais que la
propriété 'length' ne donne pas la bonne valeur (c'est le nombre de
seizets UTF-16). Comment puis-je faire ?
Cordialement,
--
Olivier Miakinen
fr.comp.lang.javascript
(
Bonjour,
Je ne suis pas sûr de répondre à la question mais:
<script>
function encode_utf8(s) {
return unescape(encodeURIComponent(s));
}
function decode_utf8(s) {
return decodeURIComponent(escape(s));
}
var str = "Ça";
alert("String: "+str+"nEncoded: "+encode_utf8(str)+"nLength: "+encode_utf8(str).length);
alert("Chaine: "+encode_utf8(str)+"nLongueur: "+encode_utf8(str).length);
</script>
Ce cote executé dans Seamonkey (caractères d'encodage "Unicode") renvoie
une alert avec:
String: Ça
Encoded: Ãa
Length: 3
À noter que si j'emploie "western" comme jeu de charactères d'affichage,
l'alert devient:
String: Ça
Encoded: Ãâ¡a
Length: 6
--
C'est juste une fille un peu brutale Qui déchire mes chemises, mes
futals En me disant : "Fais gaffe, baba cool : Je mets mes crampons,
gare tes bidoules.
-- H.F. Thiéfaine, Groupie 89 turbo 6
En effet, « unescape(encodeURIComponent(s)).length » semble répondre
parfaitement à ma question. En tout cas ça donne le bon résultat pour
tous les tests que j'ai faits, en particulier :
"e" -> 1
"é" -> 2
"€" -> 3
"
Déjà, à condition d'englober le tout par un try ... catch, ça permet de
détecter les chaînes mal formées telles que "uD800".
Il n'y a pas de solution simple AMHA, a part parcourir tous les
caractères, et tester les intervalles: (tests a effectuer dans cet ordre)
[ 0xD800 .. 0xDC00 [ : ajouter 4
[ 0xDC00 .. 0xE000 [ : ne rien faire
[ 0x0000 .. 0x007F [ : ajouter 1
[ 0x0080 .. 0x07FF [ : ajouter 2
[ 0x0800 .. 0xFFFF [ : ajouter 3
L'idée étant que l'on peut prendre en compte uniquement les "high
surrogates" qui donneront un point supérieur a FFFF (donc 4 octets) et
ignorer les "low surrogates".
Mais il y a peut être un solution plus efficace ...
Voir:
http://en.wikipedia.org/wiki/UTF-8#Description
http://en.wikipedia.org/wiki/UTF-16
Tu viens de me donner une idée...
var re = /([u0080-u07FFuD800-uDFFF])|([u0800-uFFFF])/g;
var length = str.replace(re, "$1$1$2$2$2").length;
Je double tous les caractères dans la zone U+0080 .. U+07FF ainsi
que tous les surrogates (high et low), et je triple ceux de la
zone U+0800 .. U+FFFF, puis j'en demande la longueur.
Ainsi, un "e" reste "e", un "é" devient "éé", un "€" devient "€€€",
et un "