将非Unicode二进制字符串转换为Javascript中的字节数组

3
我使用ajax从Web服务器读取了一个二进制文件。HTTP响应的contentType为'application/octet-stream',包含一个二进制字符串,它只是一串字节(不是Unicode),例如(十六进制):
0x00 0x08 0x17 0xA1 0x01
注意:在C中,这将表示为内存中的5个字节:
char buf[5] = {0, 8, 23, 161, 1}

...但在Javascript中,它是一个字符串,ASCII表示形式类似于“ �”(我实际上无法正确粘贴它,因为并非所有字符都具有可打印的表示形式)。

现在我需要将其转换为字符或整数数组,以便可以访问字符串中每个字符的数值。但是,使用charCodeAt()函数迭代示例字符串会返回:

[0] 0
[1] 8
[2] 23
[3] 65533
[4] 1

因为charCodeAt()解码unicode字符,而0xA1不被认为是有效的unicode字符,所以会使用替换字符(65533)代替它。
我想得到以下内容:
[0] 0
[1] 8
[2] 23
[3] 161
[4] 1

如何实现这一点? 以下是代码片段:
$.ajax({
url: url,
type: "get",
success: function(data) { // data contains binary representation of 0x00 0x08 0x17 0xA1 0x01
    var byteTab = []
    for (var n = 0; n < data.length; ++n) {
        byteTab.push(data.charCodeAt(n))
    }
})
2个回答

1

根据Haus的答案中提到的suggestion,我找到了更多解决问题的方法,现在我将在这里分享我的发现。

  1. My preferred solution is to use ArrayBuffer to access raw data. Unfortunately Ajax does not seem to support it as per this article, although there is an option to add support (which I could not get to work), and there is no straightforward way to create an ArrayBuffer out of string. However XMLHttpRequest supports ArrayBuffer as responseType as explained here so I changed my code to the following, which does what I want:

    var xhr = new XMLHttpRequest();
    xhr.open('GET', url);
    xhr.responseType = 'arraybuffer';  
    xhr.onload = function() {
        if (this.status == 200) {
            var byteTab=[]
            var uint8View = new Uint8Array(this.response)
            for (var n = 0; n < uint8View.byteLength; n++) {
                byteTab.push(uint8View[n])
            }
    
        } 
    };
    xhr.send();
    
  2. Another solution is to get to ArrayBuffer via using Blob, which is explained with an example in this answer

  3. Another option is to use Blob in conjunction with FileReader.readAsBinaryString() along the lines of the example here. Using readAsBinaryString() converts the blob to a unicode string which can then be parsed using charCodeAt()


1

更新:我不确定在这种情况下[默认] Ajax 是否是正确的工具。无论文件大小如何,使用流进行操作通常是一个好习惯,以适应未来的可扩展性,因为当前方法会一次性加载所有内容。

本文介绍了如何创建一个自定义的Ajax传输器,将数据加载到数组缓冲区中的XmlHttpRequest中。您可以这样做,顺序地将字节推入主数组,然后从那里开始。

旧:我不确定是否正确理解了您的数据表示方式,但我认为您可以使用parseInt()将十六进制字符串转换为十进制数:

var data = ['0x00', '0x08', '0x17', '0xA1', '0x01'];
var parsed = [];

for(var i = 0; i < data.length; i++) {
 parsed.push(parseInt(data[i], 16));
}

console.log(parsed);
console.log(parseInt('0xA1', 16))

如果这不是你想要的,请留言,我会尝试更新我的答案以获得更具体的实现。

如果我的问题在某些方面不清楚,我很抱歉 - 我现在已经更新了问题。在我的代码片段中,从Web服务器返回的“data”缓冲区内容是一个对应于5个字节的字符串。在C中,这可以表示为:char buf [5] = {0、8、23、161、1}。在Javascript中,它被返回为长度为5的字符串。由于Javascript不像C那样操作“字节”或“字符”,所以我无法找到一种方法来获取此字符串中各个字符的数字值,因为其中一些值如0xA1(161)不是Unicode字符。 - Kane

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接