La longueur de la chaîne en octets en JavaScript
Dans mon code JavaScript j'ai besoin de rédiger un message à un serveur dans ce format:
<size in bytes>CRLF
<data>CRLF
Exemple:
3
foo
Les données peuvent contenir des caractères unicode. J'ai besoin de les envoyer, comme UTF-8.
Je suis à la recherche pour la plupart de la croix-navigateur de façon à calculer la longueur de la chaîne en octets en JavaScript.
J'ai essayé de composer ma charge utile:
return unescape(encodeURIComponent(str)).length + "\n" + str + "\n"
Mais il ne me donne pas de résultats précis pour les anciens navigateurs (ou, peut-être les cordes dans ces navigateurs en UTF-16?).
Toute indices?
Mise à jour:
Exemple: longueur en octets de la chaîne ЭЭХ! Naïve?
en UTF-8 est de 15 octets, mais certains navigateurs rapport de 23 octets au lieu.
- Double Possible? stackoverflow.com/questions/2219526/...
- aucune des réponses à la question que vous avez lié à travailler pour moi.
- Quand vous parlez de "ЭЭХ! Naïf?" avez vous la mettez dans un particulier forme normale? unicode.org/reports/tr15
- J'ai tapé au hasard éditeur de texte (en mode UTF-8) et l'a sauvé. Tout comme n'importe quel utilisateur de ma bibliothèque devrait le faire. Cependant, il semble que j'ai compris ce qui n'allait pas — voir ma réponse.
Vous devez vous connecter pour publier un commentaire.
Il n'y a aucun moyen de le faire en JavaScript natif.(Voir Riccardo Galli réponse pour une approche moderne.)Pour référence historique ou où TextEncoder Api sont toujours indisponible.
Si vous connaissez le codage des caractères, vous pouvez calculer vous-même si.
encodeURIComponent
suppose l'UTF-8 comme encodage des caractères, donc si vous avez besoin que l'encodage, vous pouvez le faire,Cela devrait fonctionner en raison de la façon UTF-8 code multi-séquences d'octets. Le premier octet codé commence toujours avec un peu élevé de zéro pour une seule séquence d'octets, ou un octet dont le premier chiffre hexadécimal est C, D, E ou F. La deuxième et les suivantes octets sont ceux dont les deux premiers bits sont 10. Ce sont les octets supplémentaires que vous souhaitez compter en UTF-8.
La table dans wikipédia rend plus claire
Si, au contraire, vous avez besoin de comprendre le codage de la page, vous pouvez utiliser cette astuce:
unescape(encodeURIComponent(str)).length
fonctionnerait que sistr
est en UTF-8?lengthInPageEncoding
suggère que c'est une longueur en caractères. Est-ce exact? J'ai besoin de la longueur de octets. (Désolé pour la question stupide.)unescape(encodeURIComponent(str)).length
de ne pas faire quelque chose d'utile depuisunescape
n'des choses différentes sur différentes plates-formes.decodeURIComponent(encodeURIComponent(str)).length
ne fera que vous donnerstr.length
. Voir xkr.us/articles/javascript/encoder-comparerlengthInPageEncoding
fonction, est-ce correct?unescape
: la chose étrange est que tous les navigateurs sur browsershots.org affichage de la chaîne correcte de la taille de la chaîne UTF-8 que j'ai testé au moins (voir url dans ma réponse). Est-ce un hasard?lengthInUtf8Bytes
fonction renvoie 5 pour les non-BMP personnagesstr.length
pour ces retours 2. Je vais écrire une version modifiée de cette fonction pour des réponses.''.length == 2
) même si il n'y a qu' un caractère Unicode il n'. La personne porteuse moitiés sont exposés comme s'ils étaient des personnages:'' == '\uD834\uDF06'
. SourceencodeURIComponent('')
est'%F0%9F%8D%80'
.unescape
n'des choses différentes sur différentes plates-formes". Sur la plate-forme neunescape
de ne pas suivre le standard? (Le comportement deunescape
dans le standard actuel est le même que dans le premier standard)unescape('%uabcd') ==== '\uabcd'
qui n'est pas pour cent de l'encodage. Autant que je me souvienne, c'était un IE changement de Netscape comportement pour le rendre plus facile pour les JS sur la non-UTF8 pages pour interagir avec IIS. Voir "%u"codage re IIS bizarreries.%uabcd
n'est pas pour cent de l'encodage (Il n'est même pas valide dans un URI selon RFC3986) - mais cela n'arrive jamais dansunescape(encodeURIComponent(...))
. Donc, je persiste à croire que "unescape(encodeURIComponent(str)).length
de ne pas faire quelque chose d'utile depuisunescape
n'des choses différentes sur différentes plates-formes." n'est pas correct. D'où vientunescape(encodeURIComponent(str)).length
pas de travail? (Voir aussi stackoverflow.com/a/619428/2770331)unescape(encodeURIComponent(str)).length
.var m = encodeURIComponent(str).match(/%[89ABab]/g); return str.length + (m ? m.length : 0);
) qui ne fonctionne pas pour codepoints à l'extérieur de la BMP (comme remarqué dans ce comment) quand à la question d'origine contenait déjà une solution, qui fonctionne partout avec tous les codepoints (return unescape(encodeURIComponent(str)).length
). Il serait bien, si ce n'était pas seulement visible dans les ...unescape(encodeURIComponent(str)).length
de ne pas faire quelque chose d'utile depuisunescape
n'des choses différentes sur différentes plates-formes." est venu à partir de heresi c'était votre question 🙂"\u0639\u0628\u0627\u0633"
.encodeURIComponent("\u0639\u0628\u0627\u0633")
? Je reçois"%D8%B9%D8%A8%D8%A7%D8%B3"
.Les années ont passé et aujourd'hui, vous pouvez le faire en natif
Noter qu'il n'est pas encore pris en charge par IE (ou Edge) (vous pouvez utiliser un polyfill pour ça).
MDN documentation
Les spécifications de la norme
TextEncode
prend en charge uniquement les utf-8 depuis Chrome 53.Ici est beaucoup plus rapide de la version, ce qui ne veut pas utiliser des expressions régulières, ni encodeURIComponent():
Ici est un performances comparaison.
Il calcule la longueur en UTF8 de chaque unicode codepoints retourné par charCodeAt() (basé sur wikipédia descriptions des UTF8, et UTF16 caractères de substitution).
Il suit RFC3629 (où les caractères UTF-8 sont au plus 4 octets de long).
Pour le simple encodage UTF-8, avec un peu meilleure compatibilité que
TextEncoder
, Blob fait le tour. Ne fonctionne pas dans les très vieux navigateurs bien.Cette fonction retourne la taille en octets de toute chaîne UTF-8 vous passer.
Source
Une autre approche très simple à l'aide de
Buffer
(uniquement pour NodeJS):En fait, j'ai compris quel est le problème. Pour que le code fonctionne la page
<head>
devrait avoir cette balise:Ou, comme suggéré dans les commentaires, si le serveur envoie une requête HTTP
Content-Encoding
en-tête, il devrait fonctionner aussi bien.Ensuite les résultats de différents navigateurs sont compatibles.
Voici un exemple:
Note: je crois que la définition de tout (précis) de codage serait résoudre le problème d'encodage. C'est juste une coïncidence que j'ai besoin de l'UTF-8.
unescape
fonction JavaScript ne devrait pas être utilisés pour décoder les Identificateurs de Ressources Uniformes (URI).unescape(encodeURIComponent(...)).length
calcule toujours la bonne longueur avec ou sansmeta http-equiv ... utf8
. Sans un encodage spécification de certains navigateurs peuvent tout simplement eu un texte différent (après codage des octets du document en texte html) dont la longueur, ils ont calculé. On peut tester facilement, par l'impression non seulement la durée, mais aussi le texte lui-même.M'a fallu du temps pour trouver une solution pour Réagir Natif donc je vais le mettre ici:
D'abord installer le
buffer
package:Alors l'utilisateur le nœud de méthode:
Ici est un organisme indépendant et efficace méthode pour compter les octets UTF-8 d'une chaîne.
JS:
Note que la méthode peut lancer d'erreur si une chaîne d'entrée est UCS-2 malformé
En NodeJS,
de la mémoire Tampon.byteLength
est une méthode spécialement à cette fin:Notez que par défaut, la méthode suppose que la chaîne est en UTF-8. Si un codage différent est requis, le passe comme deuxième argument.
strLengthInBytes
juste en sachant le compte de caractères dans la chaîne? ievar text = "Hello World!; var text_length = text.length; // pass text_length as argument to some method?
. Et, juste pour la référence, reBuffer
- je suis tombé sur cette réponse qui traite denew Blob(['test string']).size
et, dans le nœud,Buffer.from('test string').length
. Peut-être que cela aidera certaines personnes trop?Ce serait travailler pour BMP et SIP/SMP caractères.
Vous pouvez essayer ceci:
Cela fonctionne pour moi.