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

5 réponses
Avatar
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

5 réponses

Avatar
Doug713705
Le 01-01-2015, Olivier Miakinen nous expliquait dans
fr.comp.lang.javascript
(<m842jn$f69$) :

[diapublication avec f.c.n.unicode, suivi dans f.c.l.javascript seul]

Bonjour,



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 ?



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
Avatar
Olivier Miakinen
Le 01/01/2015 20:43, Doug713705 m'a répondu :

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 ?



Je ne suis pas sûr de répondre à la question mais:

<script>
function encode_utf8(s) {
return unescape(encodeURIComponent(s));
}

[...]



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
"
Avatar
Olivier Miakinen
Le 01/01/2015 23:13, je répondais à Doug Soleil :

En effet, « unescape(encodeURIComponent(s)).length » semble répondre
parfaitement à ma question. [...]

Je vais continuer à chercher pour voir s'il y a plus simple (ou si cette
méthode cache un 'loup' qui ferait qu'elle ne fonctionnerait pas dans
certains cas), mais sinon je vais l'adopter.



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".
Avatar
Xavier Roche
Le 01/01/2015 19:11, Olivier Miakinen a écrit :
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 ?



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
Avatar
Olivier Miakinen
Le 03/01/2015 17:27, Xavier Roche m'a répondu :

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 ?



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 ...



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 "