如何将字符串转换为字节数组

如何使用 JavaScript 在 bytearray 中转换字符串。

UnicodeEncoding encoding = new UnicodeEncoding();
byte[] bytes = encoding.GetBytes(AnyString);

由于 UnicodeEncoding 在缺省情况下是 UTF-16和 Little-Endianness。

编辑: 我需要将 bytearray 生成的客户端与使用上面的 C # 代码在服务器端生成的客户端进行匹配。

359362 次浏览

在 C # 中运行这个

UnicodeEncoding encoding = new UnicodeEncoding();
byte[] bytes = encoding.GetBytes("Hello");

创建一个数组

72,0,101,0,108,0,108,0,111,0

byte array

对于代码大于255的字符,它看起来是这样的

byte array

如果您希望在 JavaScript 中获得非常类似的行为,那么可以这样做(v2是一个更健壮的解决方案,而原始版本只适用于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(', '));

下面是@BrunoLM 发布的转换为 String 原型函数的相同函数:

String.prototype.getBytes = function () {
var bytes = [];
for (var i = 0; i < this.length; ++i) {
bytes.push(this.charCodeAt(i));
}
return bytes;
};

If you define the function as such, then you can call the .getBytes() method on any string:

var str = "Hello World!";
var bytes = str.getBytes();

I suppose C# and Java produce equal byte arrays. If you have non-ASCII characters, it's not enough to add an additional 0. My example contains a few special characters:

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 (Byte Order Marks) ,但是如果使用 UTF-16,JavaString.getBytes会添加以下字节: 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

编辑:

增加了一个特殊字符(U + 1 D11E) MUSICAL SYMBOL G CLEF (外部 BPM,所以采取不仅2字节的 UTF-16,但4。

当前的 JavaScript 版本在内部使用“ UCS-2”,因此该符号占用2个普通字符的空间。

我不确定,但是当使用 charCodeAt时,我们似乎得到了 UTF-16中也使用的代理代码点,所以非 BPM 字符得到了正确的处理。

这个问题绝对不是无关紧要的。它可能取决于使用的 JavaScript 版本和引擎。因此,如果你想要可靠的解决方案,你应该看看:

我现在想到的最好的解决办法(尽管很可能很粗糙)是:

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;
}

不过我注意到这个问题已经存在了一年多了。

您不需要下划线,只需使用内置的 map:

var string = 'Hello World!';


document.write(string.split('').map(function(c) { return c.charCodeAt(); }));

我知道这个问题已经有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());

或者,如果希望只使用字符串,而不使用 Array,则可以使用:

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());

Inspired by @hgoebl's answer. His code is for UTF-16 and I needed something for US-ASCII. So here's a more complete answer covering US-ASCII, UTF-16, and 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是可变长度的,不包括在内,因为我必须自己编写编码。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(和谐)提案的一部分。因为 charCodeAt 返回2个字节,这比 US-ASCII 所能表示的字符数更多,所以函数 stringToAsciiByteArray会在这种情况下抛出这些字符,而不是将字符分成两半并接受其中一个或两个字节。

请注意,这个答案是非平凡的,因为字符编码是非平凡的。你想要什么样的字节数组取决于你想要这些字节代表什么样的字符编码。

javascript has the option of internally using either UTF-16 or UCS-2 but since it has methods that act like it is UTF-16 I don't see why any browser would use UCS-2. 另见: < a href = “ https://mathiasbynens.be/note/javascript-coding”rel = “ nofollow norefrer”> https://mathiasbynens.be/notes/javascript-encoding

是的,我知道这个问题是4岁,但我需要这个答案为我自己。

如果您正在寻找一个可以在 node.js 中工作的解决方案,您可以使用以下方法:

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);

既然我不能对答案发表评论,那么我将以 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

因此,汤姆 · 斯蒂克尔的反对是无效的,答案确实是有效的。

更新2018年 -2018年最简单的方法应该是 < a href = “ https://developer.mozilla.org/en-US/docs/Web/API/TextEncoder”rel = “ noReferrer”> TextEncoder

let utf8Encode = new TextEncoder();
utf8Encode.encode("abc");
// Uint8Array [ 97, 98, 99 ]

警告 -返回的元素是 Uint8Array并非所有浏览器都支持

String.prototype.encodeHex = function () {
return this.split('').map(e => e.charCodeAt())
};


String.prototype.decodeHex = function () {
return this.map(e => String.fromCharCode(e)).join('')
};

UTF-16字节数组

JavaScript encodes strings as UTF-16, just like C#'s UnicodeEncoding, so creating a byte array is relatively straightforward.

JavaScript 的 charCodeAt()返回一个16位的 代码单元(即0到65535之间的2字节整数)。您可以使用以下方法将其拆分为不同的字节:

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;
}

例如:

strToUtf16Bytes('🌵');
// [ 60, 216, 53, 223 ]

This works between C# and JavaScript because they both support UTF-16. However, if you want to get a UTF-8 byte array from JS, you must transcode the bytes.

UTF-8字节数组

这个解决方案看起来有些不简单,但我在生产环境中使用了下面的代码,并取得了很大的成功(original source)。

Also, for the interested reader, I published 我的 Unicode 助手 that help me work with string lengths reported by other languages such as 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;
}