Le .charCodeAt
La fonction retourne avec le code unicode du caractère. Mais je voudrais plutôt obtenir le tableau d'octets. Je sais que si le code de caractère est supérieur à 127, le caractère est stocké dans deux octets ou plus.
var arr=[];
for(var i=0; i<str.length; i++) {
arr.Push(str.charCodeAt(i))
}
La logique de codage Unicode en UTF-8 est la suivante:
Voici une fonction que j'ai écrite il y a longtemps pour encoder une chaîne JavaScript UTF-16 en UTF-8:
function toUTF8Array(str) {
var utf8 = [];
for (var i=0; i < str.length; i++) {
var charcode = str.charCodeAt(i);
if (charcode < 0x80) utf8.Push(charcode);
else if (charcode < 0x800) {
utf8.Push(0xc0 | (charcode >> 6),
0x80 | (charcode & 0x3f));
}
else if (charcode < 0xd800 || charcode >= 0xe000) {
utf8.Push(0xe0 | (charcode >> 12),
0x80 | ((charcode>>6) & 0x3f),
0x80 | (charcode & 0x3f));
}
// surrogate pair
else {
i++;
// UTF-16 encodes 0x10000-0x10FFFF by
// subtracting 0x10000 and splitting the
// 20 bits of 0x0-0xFFFFF into two halves
charcode = 0x10000 + (((charcode & 0x3ff)<<10)
| (str.charCodeAt(i) & 0x3ff));
utf8.Push(0xf0 | (charcode >>18),
0x80 | ((charcode>>12) & 0x3f),
0x80 | ((charcode>>6) & 0x3f),
0x80 | (charcode & 0x3f));
}
}
return utf8;
}
JavaScript String
s are stocké dans UTF-16 . Pour obtenir UTF-8, vous devrez convertir vous-même le String
.
Une solution consiste à mélanger encodeURIComponent()
, ce qui générera un octet UTF-8 codé en URL, avec unescape
, comme mentionné sur ecmanaut .
var utf8 = unescape(encodeURIComponent(str));
var arr = [];
for (var i = 0; i < utf8.length; i++) {
arr.Push(utf8.charCodeAt(i));
}
La nouvelle API de codage semble vous permettre à la fois de coder et de décoder UTF-8 facilement (à l'aide de tableaux typés):
var encoded = new TextEncoder("utf-8").encode("Γεια σου κόσμε");
var decoded = new TextDecoder("utf-8").decode(encoded);
console.log(encoded, decoded);
Support du navigateur c'est pas mal , et il y a un polyfill qui devrait fonctionner dans IE11 et les versions antérieures d'Edge.
L'API prend également en charge de nombreux encodages différents. Je l'ai utilisé pour décoder/encoder du texte japonais (Shift-JIS) avec ceci:
new TextDecoder("shift-jis").decode(new Uint8Array(textbuffer))
La bibliothèque Google Closure possède des fonctions permettant de convertir en/à partir des tableaux UTF-8 et byte. Si vous ne voulez pas utiliser toute la bibliothèque, vous pouvez copier les fonctions de ici . Pour être complet, le code à convertir en chaîne en un tableau d'octets UTF-8 est:
goog.crypt.stringToUtf8ByteArray = function(str) {
// TODO(user): Use native implementations if/when available
var out = [], p = 0;
for (var i = 0; i < str.length; i++) {
var c = str.charCodeAt(i);
if (c < 128) {
out[p++] = c;
} else if (c < 2048) {
out[p++] = (c >> 6) | 192;
out[p++] = (c & 63) | 128;
} else if (
((c & 0xFC00) == 0xD800) && (i + 1) < str.length &&
((str.charCodeAt(i + 1) & 0xFC00) == 0xDC00)) {
// Surrogate Pair
c = 0x10000 + ((c & 0x03FF) << 10) + (str.charCodeAt(++i) & 0x03FF);
out[p++] = (c >> 18) | 240;
out[p++] = ((c >> 12) & 63) | 128;
out[p++] = ((c >> 6) & 63) | 128;
out[p++] = (c & 63) | 128;
} else {
out[p++] = (c >> 12) | 224;
out[p++] = ((c >> 6) & 63) | 128;
out[p++] = (c & 63) | 128;
}
}
return out;
};
En supposant que la question concerne une chaîne DOMString en entrée et que le but est d'obtenir un tableau, qui, interprété comme une chaîne (écrite dans un fichier sur le disque, par exemple), serait encodé en UTF-8:
Maintenant que presque tous les navigateurs modernes supporte Typed Arrays , il serait honteux que cette approche ne soit pas listée:
.readAsArrayBuffer()
d’un lecteur de fichiers Exemple:
// Create a Blob with an Euro-char (U+20AC)
var b = new Blob(['€']);
var fr = new FileReader();
fr.onload = function() {
ua = new Uint8Array(fr.result);
// This will log "3|226|130|172"
// E2 82 AC
// In UTF-16, it would be only 2 bytes long
console.log(
fr.result.byteLength + '|' +
ua[0] + '|' +
ua[1] + '|' +
ua[2] + ''
);
};
fr.readAsArrayBuffer(b);
Jouez avec ça sur JSFiddle . Je n'ai pas encore analysé ce point de vue, mais je peux imaginer que cela soit efficace pour les grandes chaînes DOMString.
Vous pouvez enregistrer une chaîne brute telle quelle en utilisant FileReader.
Enregistrez la chaîne dans un blob et appelez readAsArrayBuffer () . Ensuite, l'événement onload génère un tampon de matrice pouvant être converti en Uint8Array. Malheureusement, cet appel est asynchrone.
Cette petite fonction vous aidera à:
function stringToBytes(str)
{
let reader = new FileReader();
let done = () => {};
reader.onload = event =>
{
done(new Uint8Array(event.target.result), str);
};
reader.readAsArrayBuffer(new Blob([str], { type: "application/octet-stream" }));
return { done: callback => { done = callback; } };
}
Appelez ça comme ça:
stringToBytes("\u{1f4a9}").done(bytes =>
{
console.log(bytes);
});
sortie:[240, 159, 146, 169]
explication:
JavaScript utilise UTF-16 et des paires de substitution pour stocker des caractères Unicode en mémoire. Pour enregistrer un caractère unicode dans des flux d'octets binaires bruts, un codage est nécessaire. UTF-8 est généralement utilisé dans ce cas. Si vous n’utilisez pas d’encodage, vous ne pouvez pas sauvegarder de caractères Unicode, il suffit de ASCII jusqu’à 0x7f.
FileReader.readAsArrayBuffer () utilise UTF-8.
J'utilisais solution de Joni et cela a bien fonctionné, mais celui-ci est beaucoup plus court.
Cela a été inspiré par la fonction atobUTF16 () de la solution n ° 3 de discussion Unicode en Base64 de Mozilla
function convertStringToUTF8ByteArray(str) {
let binaryArray = new Uint8Array(str.length)
Array.prototype.forEach.call(binaryArray, function (el, idx, arr) { arr[idx] = str.charCodeAt(idx) })
return binaryArray
}