Comment puis-je convertir une chaîne dans bytearray en utilisant JavaScript. La sortie doit être équivalente au code C # ci-dessous.
UnicodeEncoding encoding = new UnicodeEncoding();
byte[] bytes = encoding.GetBytes(AnyString);
Comme UnicodeEncoding est par défaut UTF-16 avec Little-Endianness.
Edit: J'ai une exigence pour faire correspondre le côté client généré par bytearray avec celui généré côté serveur en utilisant le code C # ci-dessus.
javascript
shas
la source
la source
Réponses:
En C # exécutant ceci
UnicodeEncoding encoding = new UnicodeEncoding(); byte[] bytes = encoding.GetBytes("Hello");
Créera un tableau avec
72,0,101,0,108,0,108,0,111,0
Pour un caractère dont le code est supérieur à 255, il ressemblera à ceci
Si vous voulez un comportement très similaire en JavaScript, vous pouvez le faire (la v2 est une solution un peu plus robuste, tandis que la version originale ne fonctionnera que pour 0x00 ~ 0xff)
var str = "Hello竜"; var bytes = []; // char codes var bytesv2 = []; // char codes for (var i = 0; i < str.length; ++i) { var code = str.charCodeAt(i); bytes = bytes.concat([code]); bytesv2 = bytesv2.concat([code & 0xff, code / 256 >>> 0]); } // 72, 101, 108, 108, 111, 31452 console.log('bytes', bytes.join(', ')); // 72, 0, 101, 0, 108, 0, 108, 0, 111, 0, 220, 122 console.log('bytesv2', bytesv2.join(', '));
la source
Si vous recherchez une solution qui fonctionne dans node.js, vous pouvez utiliser ceci:
var myBuffer = []; var str = 'Stack Overflow'; var buffer = new Buffer(str, 'utf16le'); for (var i = 0; i < buffer.length; i++) { myBuffer.push(buffer[i]); } console.log(myBuffer);
la source
Je suppose que C # et Java produisent des tableaux d'octets égaux. Si vous avez des caractères non ASCII, il ne suffit pas d'ajouter un 0 supplémentaire. Mon exemple contient quelques caractères spéciaux:
var str = "Hell ö € Ω 𝄞"; var bytes = []; var charCode; for (var i = 0; i < str.length; ++i) { charCode = str.charCodeAt(i); bytes.push((charCode & 0xFF00) >> 8); bytes.push(charCode & 0xFF); } alert(bytes.join(' ')); // 0 72 0 101 0 108 0 108 0 32 0 246 0 32 32 172 0 32 3 169 0 32 216 52 221 30
Je ne sais pas si C # place BOM (Byte Order Marks), mais si vous utilisez UTF-16, Java
String.getBytes
ajoute les octets suivants: 254255.String s = "Hell ö € Ω "; // now add a character outside the BMP (Basic Multilingual Plane) // we take the violin-symbol (U+1D11E) MUSICAL SYMBOL G CLEF s += new String(Character.toChars(0x1D11E)); // surrogate codepoints are: d834, dd1e, so one could also write "\ud834\udd1e" byte[] bytes = s.getBytes("UTF-16"); for (byte aByte : bytes) { System.out.print((0xFF & aByte) + " "); } // 254 255 0 72 0 101 0 108 0 108 0 32 0 246 0 32 32 172 0 32 3 169 0 32 216 52 221 30
Éditer:
Ajout d'un caractère spécial (U + 1D11E) SYMBOLE MUSICAL G CLEF (en dehors de BPM, prenant donc non seulement 2 octets en UTF-16, mais 4.
Les versions actuelles de JavaScript utilisent "UCS-2" en interne, donc ce symbole prend l'espace de 2 caractères normaux.
Je ne suis pas sûr, mais lors de son utilisation,
charCodeAt
il semble que nous obtenons exactement les points de code de substitution également utilisés dans UTF-16, de sorte que les caractères non BPM sont gérés correctement.Ce problème est absolument non trivial. Cela peut dépendre des versions et des moteurs JavaScript utilisés. Donc, si vous voulez des solutions fiables, vous devriez jeter un œil à:
la source
charCodeAt
renvoie une unité de code UTF-16, comprise entre 0 et 65535. Les caractères en dehors de la plage de 2 octets sont représentés comme des paires de substitution, tout comme en UTF-16. (À propos, cela est vrai pour les chaînes dans plusieurs autres langues, y compris Java et C #.)(charCode & 0xFF00) >> 8
c'est redondant, vous n'avez pas besoin de le masquer avant de changer de vitesse.Le moyen le plus simple en 2018 devrait être TextEncoder mais l'élément renvoyé n'est pas un tableau d'octets, c'est Uint8Array. (Et tous les navigateurs ne le prennent pas en charge)
let utf8Encode = new TextEncoder(); utf8Encode.encode("eee") > Uint8Array [ 101, 101, 101 ]
la source
new TextDecoder().decode(new TextEncoder().encode(str)) == str
.TextEncoder
: caniuseTableau UTF-16 octets
JavaScript encode les chaînes en UTF-16 , tout comme C #
UnicodeEncoding
, de sorte que les tableaux d'octets doivent correspondre exactement en utilisantcharCodeAt()
et en divisant chaque paire d'octets retournée en 2 octets séparés, comme dans:function strToUtf16Bytes(str) { const bytes = []; for (ii = 0; ii < str.length; ii++) { const code = str.charCodeAt(ii); // x00-xFFFF bytes.push(code & 255, code >> 8); // low, high } return bytes; }
Par exemple:
strToUtf16Bytes('🌵'); // [ 60, 216, 53, 223 ]
Cependant, si vous souhaitez obtenir un tableau d'octets UTF-8, vous devez transcoder les octets.
Tableau UTF-8 octets
La solution semble quelque peu non triviale, mais j'ai utilisé le code ci-dessous dans un environnement de production à fort trafic avec beaucoup de succès ( source d'origine ).
Aussi, pour le lecteur intéressé, j'ai publié mes helpers unicode qui m'aident à travailler avec des longueurs de chaîne rapportées par d'autres langages tels que PHP.
/** * Convert a string to a unicode byte array * @param {string} str * @return {Array} of bytes */ export function strToUtf8Bytes(str) { const utf8 = []; for (let ii = 0; ii < str.length; ii++) { let charCode = str.charCodeAt(ii); 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)); } else { ii++; // Surrogate pair: // 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(ii) & 0x3ff)); utf8.push( 0xf0 | (charCode >> 18), 0x80 | ((charCode >> 12) & 0x3f), 0x80 | ((charCode >> 6) & 0x3f), 0x80 | (charCode & 0x3f), ); } } return utf8; }
la source
Inspiré par la réponse de @ hgoebl. Son code est pour UTF-16 et j'avais besoin de quelque chose pour US-ASCII. Voici donc une réponse plus complète couvrant US-ASCII, UTF-16 et UTF-32.
/**@returns {Array} bytes of US-ASCII*/ function stringToAsciiByteArray(str) { var bytes = []; for (var i = 0; i < str.length; ++i) { var charCode = str.charCodeAt(i); if (charCode > 0xFF) // char > 1 byte since charCodeAt returns the UTF-16 value { throw new Error('Character ' + String.fromCharCode(charCode) + ' can\'t be represented by a US-ASCII byte.'); } bytes.push(charCode); } return bytes; } /**@returns {Array} bytes of UTF-16 Big Endian without BOM*/ function stringToUtf16ByteArray(str) { var bytes = []; //currently the function returns without BOM. Uncomment the next line to change that. //bytes.push(254, 255); //Big Endian Byte Order Marks for (var i = 0; i < str.length; ++i) { var charCode = str.charCodeAt(i); //char > 2 bytes is impossible since charCodeAt can only return 2 bytes bytes.push((charCode & 0xFF00) >>> 8); //high byte (might be 0) bytes.push(charCode & 0xFF); //low byte } return bytes; } /**@returns {Array} bytes of UTF-32 Big Endian without BOM*/ function stringToUtf32ByteArray(str) { var bytes = []; //currently the function returns without BOM. Uncomment the next line to change that. //bytes.push(0, 0, 254, 255); //Big Endian Byte Order Marks for (var i = 0; i < str.length; i+=2) { var charPoint = str.codePointAt(i); //char > 4 bytes is impossible since codePointAt can only return 4 bytes bytes.push((charPoint & 0xFF000000) >>> 24); bytes.push((charPoint & 0xFF0000) >>> 16); bytes.push((charPoint & 0xFF00) >>> 8); bytes.push(charPoint & 0xFF); } return bytes; }
UTF-8 est de longueur variable et n'est pas inclus car je devrais écrire l'encodage moi-même. UTF-8 et UTF-16 sont de longueur variable. UTF-8, UTF-16 et UTF-32 ont un nombre minimum de bits comme leur nom l'indique. Si un caractère UTF-32 a un point de code de 65, cela signifie qu'il y a 3 0 non significatifs. Mais le même code pour UTF-16 n'a qu'un seul 0 en tête. L'US-ASCII, en revanche, est de largeur fixe de 8 bits, ce qui signifie qu'il peut être directement traduit en octets.
String.prototype.charCodeAt
renvoie un nombre maximum de 2 octets et correspond exactement à UTF-16. Cependant pour UTF-32String.prototype.codePointAt
est nécessaire qui fait partie de la proposition ECMAScript 6 (Harmony). Étant donné que charCodeAt renvoie 2 octets, ce qui est plus de caractères possibles que l'US-ASCII ne peut représenter, la fonctionstringToAsciiByteArray
lancera dans de tels cas au lieu de diviser le caractère en deux et de prendre l'un ou les deux octets.Notez que cette réponse n'est pas triviale car le codage des caractères n'est pas trivial. Le type de tableau d'octets souhaité dépend du codage de caractères que vous souhaitez que ces octets représentent.
javascript a la possibilité d'utiliser en interne UTF-16 ou UCS-2, mais comme il a des méthodes qui agissent comme UTF-16, je ne vois pas pourquoi un navigateur utiliserait UCS-2. Voir aussi: https://mathiasbynens.be/notes/javascript-encoding
Oui, je sais que la question a 4 ans mais j'avais besoin de cette réponse pour moi-même.
la source
'02'
sont[ 48, 0, 50, 0 ]
où votrestringToUtf16ByteArray
fonction retourne[ 0, 48, 0, 50 ]
. laquelle est correcte?Puisque je ne peux pas commenter la réponse, je miserais sur la réponse de Jin Izzraeel
en disant que vous pouvez l'utiliser si vous souhaitez utiliser un tampon Node.js dans votre navigateur.
https://github.com/feross/buffer
Par conséquent, l'objection de Tom Stickel n'est pas valable et la réponse est en effet une réponse valable.
la source
String.prototype.encodeHex = function () { return this.split('').map(e => e.charCodeAt()) }; String.prototype.decodeHex = function () { return this.map(e => String.fromCharCode(e)).join('') };
la source
encodeHex
renverra un tableau de nombres 16 bits, pas d'octets.La meilleure solution que j'ai trouvée sur place (bien que probablement brute) serait:
String.prototype.getBytes = function() { var bytes = []; for (var i = 0; i < this.length; i++) { var charCode = this.charCodeAt(i); var cLen = Math.ceil(Math.log(charCode)/Math.log(256)); for (var j = 0; j < cLen; j++) { bytes.push((charCode << (j*8)) & 0xFF); } } return bytes; }
Bien que je remarque que cette question est là depuis plus d'un an.
la source
charCodeAt
renvoie une unité de code UTF-16 16 bits, vous n'avez donc pas besoin de logique de longueur variable. Vous pouvez simplement appeler charCodeAt, diviser le résultat en deux octets de 8 bits et les insérer dans le tableau de sortie (octet de poids faible en premier puisque la question demande UTF-16LE).Je sais que la question a presque 4 ans, mais c'est ce qui a fonctionné sans problème avec moi:
String.prototype.encodeHex = function () { var bytes = []; for (var i = 0; i < this.length; ++i) { bytes.push(this.charCodeAt(i)); } return bytes; }; Array.prototype.decodeHex = function () { var str = []; var hex = this.toString().split(','); for (var i = 0; i < hex.length; i++) { str.push(String.fromCharCode(hex[i])); } return str.toString().replace(/,/g, ""); }; var str = "Hello World!"; var bytes = str.encodeHex(); alert('The Hexa Code is: '+bytes+' The original string is: '+bytes.decodeHex());
ou, si vous souhaitez travailler uniquement avec des chaînes et pas de tableau, vous pouvez utiliser:
String.prototype.encodeHex = function () { var bytes = []; for (var i = 0; i < this.length; ++i) { bytes.push(this.charCodeAt(i)); } return bytes.toString(); }; String.prototype.decodeHex = function () { var str = []; var hex = this.split(','); for (var i = 0; i < hex.length; i++) { str.push(String.fromCharCode(hex[i])); } return str.toString().replace(/,/g, ""); }; var str = "Hello World!"; var bytes = str.encodeHex(); alert('The Hexa Code is: '+bytes+' The original string is: '+bytes.decodeHex());
la source
bytes
tableau ne contient pas d'octets, il contient des nombres de 16 bits, qui représentent la chaîne en unités de code UTF-16. C'est à peu près ce que la question demandait, mais vraiment par accident.Voici la même fonction que @BrunoLM a publiée convertie en fonction prototype String:
String.prototype.getBytes = function () { var bytes = []; for (var i = 0; i < this.length; ++i) { bytes.push(this.charCodeAt(i)); } return bytes; };
Si vous définissez la fonction en tant que telle, vous pouvez appeler la méthode .getBytes () sur n'importe quelle chaîne:
var str = "Hello World!"; var bytes = str.getBytes();
la source
Vous n'avez pas besoin de soulignement, utilisez simplement la carte intégrée:
var string = 'Hello World!'; document.write(string.split('').map(function(c) { return c.charCodeAt(); }));
la source