Bagaimana saya bisa mengubah string dalam bytearray menggunakan JavaScript. Output harus setara dengan kode C # di bawah ini.
UnicodeEncoding encoding = new UnicodeEncoding();
byte[] bytes = encoding.GetBytes(AnyString);
Karena UnicodeEncoding secara default dari UTF-16 dengan Little-Endianness.
Sunting: Saya memiliki persyaratan untuk mencocokkan sisi klien yang dihasilkan bytearray dengan yang dihasilkan di sisi server menggunakan kode C # di atas.
javascript
shas
sumber
sumber
Jawaban:
Dalam C # menjalankan ini
UnicodeEncoding encoding = new UnicodeEncoding(); byte[] bytes = encoding.GetBytes("Hello");
Akan membuat array dengan
72,0,101,0,108,0,108,0,111,0
Untuk karakter yang kodenya lebih besar dari 255 akan terlihat seperti ini
Jika Anda menginginkan perilaku yang sangat mirip di JavaScript, Anda dapat melakukan ini (v2 adalah solusi yang sedikit lebih kuat, sedangkan versi aslinya hanya akan berfungsi untuk 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(', '));
sumber
Jika Anda mencari solusi yang berfungsi di node.js, Anda dapat menggunakan ini:
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);
sumber
Saya kira C # dan Java menghasilkan array byte yang sama. Jika Anda memiliki karakter non-ASCII, itu tidak cukup untuk menambahkan tambahan 0. Contoh saya berisi beberapa karakter khusus:
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
Saya tidak tahu apakah C # menempatkan BOM (Byte Order Marks), tetapi jika menggunakan UTF-16, Java
String.getBytes
menambahkan byte berikut: 254 255.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
Edit:
Menambahkan karakter khusus (U + 1D11E) MUSICAL SYMBOL G CLEF (di luar BPM, jadi mengambil tidak hanya 2 byte dalam UTF-16, tetapi 4.
Versi JavaScript saat ini menggunakan "UCS-2" secara internal, jadi simbol ini menggunakan spasi 2 karakter normal.
Saya tidak yakin, tetapi saat menggunakannya
charCodeAt
tampaknya kami mendapatkan titik kode pengganti yang juga digunakan dalam UTF-16, jadi karakter non-BPM ditangani dengan benar.Masalah ini sama sekali tidak sepele. Ini mungkin tergantung pada versi dan mesin JavaScript yang digunakan. Jadi, jika Anda menginginkan solusi yang andal, Anda harus melihat:
sumber
charCodeAt
mengembalikan Unit Kode UTF-16, dalam kisaran 0-65535. Karakter di luar rentang 2-byte direpresentasikan sebagai pasangan pengganti, seperti di UTF-16. (Ngomong-ngomong, ini juga berlaku untuk string dalam beberapa bahasa lain, termasuk Java dan C #.)(charCode & 0xFF00) >> 8
ini mubazir, Anda tidak perlu menutupinya sebelum berpindah.Cara termudah di tahun 2018 adalah TextEncoder tetapi elemen yang dikembalikan bukan byte array, melainkan Uint8Array. (Dan tidak semua browser mendukungnya)
let utf8Encode = new TextEncoder(); utf8Encode.encode("eee") > Uint8Array [ 101, 101, 101 ]
sumber
new TextDecoder().decode(new TextEncoder().encode(str)) == str
.TextEncoder
: caniuseArray UTF-16 Byte
JavaScript mengkodekan string sebagai UTF-16 , seperti C #
UnicodeEncoding
, jadi array byte harus sama persis dengan yang digunakancharCodeAt()
, dan memisahkan setiap pasangan byte yang dikembalikan menjadi 2 byte terpisah, seperti di: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; }
Sebagai contoh:
strToUtf16Bytes('🌵'); // [ 60, 216, 53, 223 ]
Namun, Jika Anda ingin mendapatkan array byte UTF-8, Anda harus mentranskode byte tersebut.
Array UTF-8 Byte
Solusinya terasa agak tidak sepele, tetapi saya menggunakan kode di bawah ini dalam lingkungan produksi dengan lalu lintas tinggi dengan kesuksesan besar ( sumber asli ).
Juga, untuk pembaca yang tertarik, saya menerbitkan pembantu unicode saya yang membantu saya bekerja dengan panjang string yang dilaporkan oleh bahasa lain seperti 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; }
sumber
Terinspirasi oleh jawaban @ hgoebl. Kodenya untuk UTF-16 dan saya membutuhkan sesuatu untuk US-ASCII. Jadi, inilah jawaban yang lebih lengkap mencakup US-ASCII, UTF-16, dan 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 memiliki panjang variabel dan tidak disertakan karena saya harus menulis pengkodeannya sendiri. UTF-8 dan UTF-16 memiliki panjang variabel. UTF-8, UTF-16, dan UTF-32 memiliki jumlah bit minimum sesuai dengan namanya. Jika karakter UTF-32 memiliki titik kode 65 maka itu berarti ada 3 awalan 0. Tetapi kode yang sama untuk UTF-16 hanya memiliki 1 awalan 0. Sebaliknya US-ASCII adalah fixed width 8-bits yang berarti dapat langsung diterjemahkan ke byte.
String.prototype.charCodeAt
mengembalikan jumlah maksimum 2 byte dan sama persis dengan UTF-16. Namun untuk UTF-32String.prototype.codePointAt
diperlukan yang merupakan bagian dari proposal ECMAScript 6 (Harmoni). Karena charCodeAt mengembalikan 2 byte yang merupakan karakter yang lebih mungkin daripada yang dapat diwakili oleh US-ASCII, fungsistringToAsciiByteArray
akan melempar dalam kasus seperti itu alih-alih membagi karakter menjadi dua dan mengambil salah satu atau kedua byte.Perhatikan bahwa jawaban ini tidak sepele karena pengkodean karakter tidak sepele. Jenis array byte yang Anda inginkan bergantung pada pengkodean karakter apa yang Anda ingin wakili oleh byte tersebut.
javascript memiliki opsi untuk menggunakan UTF-16 atau UCS-2 secara internal tetapi karena ia memiliki metode yang bertindak seperti UTF-16, saya tidak mengerti mengapa browser apa pun akan menggunakan UCS-2. Lihat juga: https://mathiasbynens.be/notes/javascript-encoding
Ya, saya tahu pertanyaannya berusia 4 tahun tetapi saya membutuhkan jawaban ini untuk diri saya sendiri.
sumber
'02'
adalah[ 48, 0, 50, 0 ]
tempatstringToUtf16ByteArray
fungsi Anda kembali[ 0, 48, 0, 50 ]
. yang mana yang benar?Karena saya tidak dapat mengomentari jawabannya, saya akan melanjutkan jawaban Jin Izzraeel
dengan mengatakan bahwa Anda dapat menggunakan ini jika Anda ingin menggunakan buffer Node.js di browser Anda.
https://github.com/feross/buffer
Oleh karena itu, keberatan Tom Stickel tidak valid, dan jawabannya memang jawaban yang valid.
sumber
String.prototype.encodeHex = function () { return this.split('').map(e => e.charCodeAt()) }; String.prototype.decodeHex = function () { return this.map(e => String.fromCharCode(e)).join('') };
sumber
encodeHex
akan mengembalikan larik angka 16-bit, bukan byte.Solusi terbaik yang saya temukan di tempat (meskipun kemungkinan besar mentah) adalah:
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; }
Meskipun saya perhatikan pertanyaan ini telah ada di sini selama lebih dari setahun.
sumber
charCodeAt
mengembalikan Unit Kode UTF-16 16-bit, jadi Anda tidak memerlukan logika panjang variabel apa pun. Anda bisa memanggil charCodeAt, membagi hasilnya menjadi dua byte 8-bit, dan memasukkannya ke dalam larik keluaran (byte urutan terendah terlebih dahulu karena pertanyaan menanyakan UTF-16LE).Saya tahu pertanyaannya sudah hampir 4 tahun, tetapi inilah yang berjalan lancar dengan saya:
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());
atau, jika Anda ingin bekerja dengan string saja, dan tanpa Array, Anda dapat menggunakan:
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());
sumber
bytes
Array tidak mengandung 'byte', berisi nomor 16-bit, yang mewakili string dalam UTF-16 unit kode. Ini hampir seperti pertanyaan yang ditanyakan, tetapi sebenarnya hanya kebetulan.Berikut adalah fungsi yang sama yang diposting oleh @BrunoLM diubah menjadi fungsi prototipe String:
String.prototype.getBytes = function () { var bytes = []; for (var i = 0; i < this.length; ++i) { bytes.push(this.charCodeAt(i)); } return bytes; };
Jika Anda mendefinisikan fungsi seperti itu, maka Anda dapat memanggil metode .getBytes () pada string apa pun:
var str = "Hello World!"; var bytes = str.getBytes();
sumber
Anda tidak perlu garis bawah, cukup gunakan peta bawaan:
var string = 'Hello World!'; document.write(string.split('').map(function(c) { return c.charCodeAt(); }));
sumber