如何将String转换为Bytearray

sha*_*has 72 javascript

如何使用JavaScript在bytearray中转换字符串.输出应该等于下面的C#代码.

UnicodeEncoding encoding = new UnicodeEncoding();
byte[] bytes = encoding.GetBytes(AnyString);
Run Code Online (Sandbox Code Playgroud)

由于UnicodeEncoding默认为UTF-16和Little-Endianness.

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

Jin*_*Jin 26

如果您正在寻找适用于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);
Run Code Online (Sandbox Code Playgroud)

  • 这是针对node.js的,但我认为问题是寻找一种在浏览器中运行的解决方案.然而,它确实可以正常工作,不像这个问题的大多数其他答案,所以+1. (3认同)
  • 截至 2021 年 11 月 5 日,“new Buffer”失败,因为 Chrome 浏览器中未定义“Buffer” (2认同)

cod*_*e4j 19

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

let utf8Encode = new TextEncoder();
utf8Encode.encode("eee")
> Uint8Array [ 101, 101, 101 ]
Run Code Online (Sandbox Code Playgroud)


Bru*_*oLM 13

在C#中运行这个

UnicodeEncoding encoding = new UnicodeEncoding();
byte[] bytes = encoding.GetBytes("Hello");
Run Code Online (Sandbox Code Playgroud)

将创建一个数组

72,0,101,0,108,0,108,0,111,0
Run Code Online (Sandbox Code Playgroud)

字节数组

对于代码大于255的字符,它将如下所示

字节数组

如果你想在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(', '));
Run Code Online (Sandbox Code Playgroud)

  • 请注意,如果字符串包含unicode字符,则charCodeAt(i)将> 255,这可能不是您想要的. (39认同)
  • 这是非常不正确的.character!= byte (35认同)
  • 是的,这是不正确的.charCodeAt不返回一个字节.将大于255的值推入名为"bytes"的数组中是没有意义的; 非常误导.此功能根本不执行编码,只是将字符代码粘贴到数组中. (22认同)
  • @shas我只在Firefox 4上测试了之前的版本.更新版本在Firefox 4,Chrome 13和IE9上进行了测试. (2认同)
  • 我不明白为什么这个答案被标记为正确,因为它没有编码任何东西。 (2认同)

hgo*_*ebl 13

我想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
Run Code Online (Sandbox Code Playgroud)

我不知道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
Run Code Online (Sandbox Code Playgroud)

编辑:

添加了一个特殊字符(U + 1D11E)MUSICAL SYMBOL G CLEF(在BPM之外,所以不仅要使用UTF-16中的2个字节,还需要4个字节.

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

我不确定但是在使用charCodeAt它时似乎我们得到了UTF-16中也使用的替代代码点,因此非正确处理非BPM字符.

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

  • @Triynko你是对的,但实际上这个答案确实有效.JavaScript字符串实际上不是Unicode代码点的序列,它们是UTF-16代码单元的序列.尽管有名称,`charCodeAt`返回UTF-16代码单元,范围为0-65535.2字节范围之外的字符表示为代理对,就像在UTF-16中一样.(顺便说一句,对于其他几种语言的字符串也是如此,包括Java和C#.) (2认同)

Sky*_*al7 9

灵感来自@ 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;
}
Run Code Online (Sandbox Code Playgroud)

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.但是,String.prototype.codePointAt需要UTF-32 ,这是ECMAScript 6(Harmony)提案的一部分.因为charCodeAt返回2个字节,这个字符比US-ASCII可以表示的字符更多,所以函数stringToAsciiByteArray将抛出这种情况,而不是将字符分成两半并取两个或两个字节.

请注意,这个答案并不重要,因为字符编码非常重要.您需要什么样的字节数组取决于您希望这些字节表示的字符编码.

javascript可以选择在内部使用UTF-16或UCS-2,但由于它的方法类似于UTF-16,我不明白为什么任何浏览器都会使用UCS-2.另见:https://mathiasbynens.be/notes/javascript-encoding

是的我知道问题是4岁但是我需要这个答案.


jch*_*ook 5

接受的答案似乎不正确。

JavaScript将字符串编码为UTF-16,因此您必须对多字节UTF-8字符进行转码。

该解决方案感觉有些不平凡,但是我在交通繁忙的生产环境中使用了以下代码,并取得了巨大的成功(原始来源)。

另外,对于感兴趣的读者,我发布了我的unicode帮助器,可帮助我处理其他语言(例如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;
}
Run Code Online (Sandbox Code Playgroud)