如何将string转换为Bytearray
如何使用Javascript在bytearray中转换string。 输出应该是以下C#代码的等价性。
UnicodeEncoding encoding = new UnicodeEncoding(); byte[] bytes = encoding.GetBytes(AnyString);
由于UnicodeEncoding默认使用Little-Endianness的UTF-16。
编辑:我有一个要求,使用上面的C#代码匹配生成的bytearray客户端和服务器端生成的客户端。
在C#中运行这个
UnicodeEncoding encoding = new UnicodeEncoding(); byte[] bytes = encoding.GetBytes("Hello");
将创build一个数组
72,0,101,0,108,0,108,0,111,0
对于代码大于255的字符,它看起来像这样
如果你想在JavaScript中使用非常类似的行为,你可以这样做(v2是一个更强大的解决scheme,而原始版本只能用于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(', '));
我猜想C#和Java产生相等的字节数组。 如果你有非ASCII字符,仅仅添加一个0是不够的。我的例子包含一些特殊字符:
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
我不知道C#是否放置BOM(字节顺序标记),但是如果使用UTF-16,Java String.getBytes
会添加以下字节: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
编辑:
增加了一个特殊字符(U + 1D11E)MUSICAL SYMBOL G CLEF(在BPM之外,所以不仅在UTF-16中占用2个字节,
目前的JavaScript版本在内部使用“UCS-2”,所以这个符号占用2个正常字符的空间。
我不确定,但是当使用charCodeAt
,好像我们得到了在UTF-16中也使用的代理代码点,所以非BPM字符被正确处理。
这个问题是绝对不平凡的。 它可能取决于使用的JavaScript版本和引擎。 所以,如果你想要可靠的解决scheme,你应该看看:
- https://github.com/koichik/node-codepoint/
- http://mathiasbynens.be/notes/javascript-escapes
- Mozilla开发者networking:charCodeAt
- BigEndian与LittleEndian
如果您正在寻找可在node.js中使用的解决scheme,则可以使用以下方法:
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);
受@ hgoebl的回答启发。 他的代码是UTF-16,我需要一些US-ASCII。 所以这里有一个更完整的答案,涵盖US-ASCII,UTF-16和UTF-32。
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; } 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; } 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是可变长度,不包括在内,因为我必须自己编写编码。 UTF-8和UTF-16是可变长度的。 UTF-8,UTF-16和UTF-32具有最小位数,正如其名称所示。 如果一个UTF-32字符的代码点为65那么这意味着有3个前导0。 但是相同的UTF-16编码只有1个前导0。另一方面,US-ASCII是固定宽度的8位,这意味着它可以直接转换为字节。
String.prototype.charCodeAt
返回2个字节的最大数目,并且与UTF-16完全匹配。 但是对于UTF-32, String.prototype.codePointAt
是ECMAScript 6(Harmony)提议的一部分。 由于charCodeAt返回2个字节,这个字符比US-ASCII可能表示的字符多,所以函数stringToAsciiByteArray
将抛出这种情况,而不是将字符分成两半,并取两个或两个字节。
请注意,这个答案是不平凡的,因为字符编码是不平凡的。 你想要什么样的字节数组取决于你想要这些字节代表什么字符编码。
javascript有内部使用UTF-16或UCS-2的选项,但是因为它具有像UTF-16一样的方法,所以我不明白为什么任何浏览器都使用UCS-2。 另见: https : //mathiasbynens.be/notes/javascript-encoding
是的,我知道这个问题是4岁,但我需要这个答案。
这里是@BrunoLM公布的转换成String原型函数的相同函数:
String.prototype.getBytes = function () { var bytes = []; for (var i = 0; i < this.length; ++i) { bytes.push(this.charCodeAt(i)); } return bytes; };
如果你这样定义函数,那么你可以在任何string上调用.getBytes()方法:
var str = "Hello World!"; var bytes = str.getBytes();
既然我不能评论答案,我会build立在Jin Izzraeel的回答上
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);
通过说你可以使用这个,如果你想在你的浏览器中使用Node.js缓冲区。
https://github.com/feross/buffer
所以Tom Stickel的反对意见是无效的,答案确实是一个有效的答案。
我现场提出的最好的解决scheme(尽pipe很可能是粗略的)是:
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; }
虽然我注意到这个问题已经在这里一年多了。
我知道这个问题已经快4岁了,但是这对我来说很顺利:
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());
你不需要下划线,只需使用内置的地图:
var string = 'Hello World!'; document.write(string.split('').map(function(c) { return c.charCodeAt(); }));