2011-06-03 141 views
56

如何使用JavaScript将字符串转换为bytearray。输出应该等于下面的C#代码。如何将字符串转换为Bytearray

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

由于UnicodeEncoding默认为使用Little-Endianness的UTF-16。

编辑:我有一个要求,使用上面的C#代码来匹配生成的bytearray客户端和服务器端生成的客户端。

+2

的JavaScript是不完全的最知名的易于使用的BLOB使用 - 你为什么不只是发送字符串的JSON? – 2011-06-03 10:58:31

+2

Javascript字符串是UTF-16,还是您已经知道了? – Kevin 2011-06-03 11:02:49

+2

首先为什么你需要在JavaScript中转换此? – BreakHead 2011-06-03 11:07:06

回答

12

在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(', '));

+1

我已经试过这个,但是这给了我不同于上面的C#代码的结果。就像这种情况一样,C#代码输出字节数组是= 72,0,101,0,108,0,108,0,111,0 我有两个匹配的要求,所以那些工作不正常。 – shas 2011-06-03 11:55:47

+0

@shas,似乎是相同的,只是在每个字符后加上一个'0'。更新后的答案现在应该和'c#'一样。 – BrunoLM 2011-06-03 12:12:27

+0

我得到了未定义的JS错误str [i]。你正在尝试访问什么。不应该是str.charCodeAt(i)? – shas 2011-06-03 12:33:04

1

下面是同样的功能@BrunoLM贴转换为字符串函数原型:

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

如果你定义的功能,例如,你可以调用.getBytes()方法的任何字符串:

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

这仍然是不正确的,就像它引用的答案一样。 charCodeAt不返回一个字节。将大于255的值推入称为“字节”的数组是没有意义的;非常误导。这个函数根本不执行编码,只是将字符代码粘贴到一个数组中。要执行UTF16编码,您必须检查字符代码,决定是否需要用2个字节或4个字节来表示它(因为UTF16是可变长度编码),然后将每个字节单独写入数组。 – Triynko 2013-08-06 21:20:55

+8

另外,修改原生数据类型的原型也是不好的做法。 – 2013-10-30 18:18:31

+0

@AndrewLundin,这是interresting ...说谁? – Jerther 2015-02-06 19:06:27

11

我想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,爪哇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标记G CLEF(BPM外部,从而不仅考虑2 UTF-16字节,但是4.

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

我不确定,但在使用charCodeAt时,看起来我们得到了UTF-16中使用的替代代码点,因此非BPM字符可以正确处理。

这个问题是绝对不平凡的。它可能取决于使用的JavaScript版本和引擎。所以,如果你想可靠的解决方案,你应该看看:

+1

仍然不是一个完整的答案。 UTF16是一种可变长度编码,它使用16位块来表示字符。单个字符将被编码为2个字节或4个字节,具体取决于charcter代码值的大小。由于此函数最多可以写入2个字节,因此无法处理所有Unicode字符代码点,并且不是一个完整的UTF16编码实现,而不是一个长镜头。 – Triynko 2013-08-06 21:24:08

+0

@Triynko我的编辑和测试后,你仍然认为这不是完整的答案?如果是,你有答案吗? – hgoebl 2013-11-09 14:18:13

+1

@Triynko你是一半的权利,但实际上这个答案确实工作正常。 JavaScript字符串实际上不是Unicode代码点的序列,它们是UTF-16代码单元的序列。尽管有这个名字,'charCodeAt'返回一个UTF-16代码单元,范围在0-65535之间。 2字节范围以外的字符表示为代理对,就像在UTF-16中一样。 (顺便说一下,对于包括Java和C#在内的其他几种语言的字符串也是如此。) – 2016-04-03 19:49:11

0

最好的解决方案我(当然最有可能的原油)会是:

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

虽然我注意到这个问题已经在这里一年多了。

+2

这不能正常工作。变长字符逻辑不正确,UTF-16中没有8位字符。尽管有这个名字,'charCodeAt'返回一个16位的UTF-16 Code Unit,所以你不需要任何可变长度的逻辑。您可以调用charCodeAt,将结果拆分为两个8位字节,并将它们填充到输出数组中(自从问题询问UTF-16LE以来,先将最低字节先填入)。 – 2016-04-03 19:58:14

-1

你不需要下划线,只需使用内置地图:

var string = 'Hello World!'; 
 

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

+0

这将返回一个16位数字的数组,表示该字符串为UTF-16代码点的序列。这不是OP要求的,但至少它让你在那里分道扬part。 – 2016-07-13 11:27:29

0

我知道这个问题几乎是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());

或者,如果你想只用字符串,并没有阵列一起,你可以使用:

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

+1

这类作品,但是非常具有误导性。 'bytes'数组不包含'bytes',它包含16位数字,代表UTF-16代码单元中的字符串。这几乎是问题的要求,但只是偶然。 – 2016-04-03 20:07:54

7

灵感来自@ 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(和谐)提案的一部分。由于charCodeAt返回2个字节,这些字符比US-ASCII可能表示的字符多,所以函数stringToAsciiByteArray将引发这种情况,而不是将字符分成两半,并取其中一个或两个字节。

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

javascript有内部使用UTF-16或UCS-2的选项,但由于它具有像UTF-16一样的方法,所以我不明白为什么任何浏览器都会使用UCS-2。 另请参阅:https://mathiasbynens.be/notes/javascript-encoding

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

14

如果您正在寻找在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); 
+2

这是为node.js,但我认为这个问题是寻找一个在浏览器中工作的解决方案。尽管如此,它确实能够正常工作,不像其他大多数对这个问题的答案,所以+1。 – 2016-04-03 19:34:14

+2

没有这样的功能BTW:/当OP没有这个对象时,新的“缓冲”,你甚至没有显示它。谁投票赞成这样的答案?问题在Javascript上,而不是Node.js - 你不能在jsfiddle或html/.js文件中使用它,并期望它可以工作。只需要NO – 2016-09-28 05:50:24

1

既然不能对答案进行评论,我会建立在金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

因此,汤姆Stickel的反对无效,答案确实是一个有效的答案。

0

2018年最简单的方法应该是TextEncoder,但返回的元素不是字节数组,它是Uint8Array。 (并非所有的浏览器都支持它)

let utf8Decode = new TextDecoder('utf-8'); 
utf8Encode.encode("eee") 
> Uint8Array [ 101, 101, 101 ] 
1
String.prototype.encodeHex = function() { 
    return this.split('').map(e => e.charCodeAt()) 
}; 

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

如果您提供一些文本以与代码一起解释为什么可以选择此方法而不是其他答案之一,这将会很有帮助。 – NightOwl888 2018-02-16 20:27:40

+0

这种方法比其他方法简单,但也是这样,这就是我没有写任何东西的原因。 – 2018-02-20 14:30:52