javascript 如何将数组缓冲区转换为字符串

vdgimpew  于 2023-03-11  发布在  Java
关注(0)|答案(4)|浏览(197)

我在node.js上编写了一个简单的TCP服务器,用于将一些数据发送到Chrome应用程序。在Chrome应用程序中,当我获取数据时,我使用以下函数将其转换为字符串,我收到一个异常“Uint16Array的字节长度应为2的倍数”

String.fromCharCode.apply(null, new Uint16Array(buffer))

我找不到任何关于是什么原因导致的以及如何修复的信息。任何关于这方面的指针都非常感谢。
下面是node.js服务器中用于向客户端发送数据的代码:

socket.on('data', function(data) {

    console.log('DATA ' + socket.remoteAddress + ': ' + data);
    // Write the data back to the socket, 
    //   the client will receive it as data from the server
    var r= socket.write('from server\r\n');

});

下面是chrome应用程序的代码:

chrome.sockets.tcp.onReceive.addListener(function (info) {
            console.log('onListener registered');
            if (info.socketId != socketid)
                return;
            else {
                try {

                   data = ab2str(info.data);
                    console.log(data);
                }
                catch (e) {
                    console.log(e);
                }

            }
            // info.data is an arrayBuffer.
        });

 function ab2str(buf) {
    return String.fromCharCode.apply(null, new Uint16Array(buf));
}
ha5z0ras

ha5z0ras1#

现代(Chrome 38+)的方法是,假设编码是UTF-8:

var decoder = new TextDecoder("utf-8");

function arrayBufferToString(buffer) {
    return decoder.decode(new Uint8Array(buffer));
}

这使用了TextDecoder API;有关更多选项,例如不同的编码,请参见documentation
另请参阅:Easier ArrayBuffer<->String conversion with the Encoding API @ Google Developers

vdzxcuhz

vdzxcuhz2#

您遇到这个问题可能是因为您的应用在套接字上接收到了奇数个字节,但您试图从中创建一个2字节宽的项数组(因为Uint16Array适合这样的项)
如果您的应用通过网络接收到字符串"Hello"(5字节),则可以将其强制转换为Uint8Array,它将如下所示:

Item:        0   1   2   3   4
Char:        H   e   l   l   o
Uint8 Value: 72  101 108 108 111

将其转换为Uint16Array,但将尝试执行以下操作:

Item   0     1     2
Chars  He    ll    o?
IntVal 25928 27756 ?????

如果没有第6个字节,它就无法构造数组,因此会出现异常。
只有在套接字上需要UCS-2字符串数据时,使用Uint16Array作为数据才有意义。如果接收的是普通ASCII数据,则需要将其转换为Uint8Array,并在其上MapString.fromCharCode。如果是其他类型,如UTF-8,则必须执行其他转换。
不过,无论如何,套接字层总是可以自由地向你发送任意长度的数据块。你的应用将不得不处理奇数大小的数据,并保存任何你无法立即处理的剩余数据,以便你在收到下一个数据块时使用它。

mum43rcc

mum43rcc3#

有点过时了,但也许使用这个函数(original source)效果更好(我用它把arraybuffer解码成string,而不会留下一些特殊的字符作为垃圾):

function decodeUtf8(arrayBuffer) {
  var result = "";
  var i = 0;
  var c = 0;
  var c1 = 0;
  var c2 = 0;

  var data = new Uint8Array(arrayBuffer);

  // If we have a BOM skip it
  if (data.length >= 3 && data[0] === 0xef && data[1] === 0xbb && data[2] === 0xbf) {
    i = 3;
  }

  while (i < data.length) {
    c = data[i];

    if (c < 128) {
      result += String.fromCharCode(c);
      i++;
    } else if (c > 191 && c < 224) {
      if( i+1 >= data.length ) {
        throw "UTF-8 Decode failed. Two byte character was truncated.";
      }
      c2 = data[i+1];
      result += String.fromCharCode( ((c&31)<<6) | (c2&63) );
      i += 2;
    } else {
      if (i+2 >= data.length) {
        throw "UTF-8 Decode failed. Multi byte character was truncated.";
      }
      c2 = data[i+1];
      c3 = data[i+2];
      result += String.fromCharCode( ((c&15)<<12) | ((c2&63)<<6) | (c3&63) );
      i += 3;
    }
  }
  return result;
}
mqkwyuun

mqkwyuun4#

有一种使用BlobFileReader异步方式。
您可以指定任何有效的编码。

function arrayBufferToString( buffer, encoding, callback ) {
    var blob = new Blob([buffer],{type:'text/plain'});
    var reader = new FileReader();
    reader.onload = function(evt){callback(evt.target.result);};
    reader.readAsText(blob, encoding);
}

//example:
var buf = new Uint8Array([65,66,67]);
arrayBufferToString(buf, 'UTF-8', console.log.bind(console)); //"ABC"

相关问题