在JavaScript中将值转换为字节数组

2 投票
1 回答
1146 浏览
提问于 2025-04-17 16:30

我正在写一个基于WebSocket网络的应用,使用的是二进制帧。我想把值从Python服务器发送到JavaScript客户端,然后再返回。

根据我的了解,打包超过8位的值时,解包和打包的方式会受到字节序(endian)的影响。可惜的是,浏览器似乎总是以小端字节序(little-endian)发送数据,而网络使用的是大端字节序(big-endian)。所以我了解到,最好的办法是把所有值打包成字节数组,这样字节序就不成问题了。

我为JavaScript写了这个函数:

valueToByteArray: function(value, bytes_length) {
    var bytes_array = [];
    for (var i=bytes_length - 1; i>=0; --i) {
        conjunction_val = 0xFF << i*8;
        shift = i*8;
        bytes_array.push((value & conjunction_val) >> shift);
    }
    return bytes_array;
}

我也为它写了测试:

test("Pack value to Byte array", function() {
    equal(
        BufferUtility.valueToByteArray(-2000000, 4),
        [255, 225, 123, 128],
        "Value packed OK"
    ); // fail returns [-1, 225, 123, 128], same function in python returns [255L, 225, 123, 128]
    equal(
        BufferUtility.valueToByteArray(4000000, 4),
        [0, 61, 9, 0],
        "Value packed OK"
    ); // pass
    equal(
        BufferUtility.valueToByteArray(0, 2),
        [0, 0],
        "Value packed OK"
    ); // pass
    equal(
        BufferUtility.valueToByteArray(-1, 2),
        [128, 1],
        "Value packed OK"
    ); // fail returns [255, 255]
});

不过只有第二个和第三个测试通过,似乎对带符号的值不太管用。我还在Python上检查了这些值,发现struct.pack('>h', -1)的结果是\xFF\xFF。老实说,我不太明白这个。因为最高位是符号位,所以我认为短整型-1的二进制应该是1000000000000001

我哪里做错了?有没有更好的方法来解决字节序的问题?

1 个回答

1

我在Freenode的#javascript频道找到了这段代码,没想到它竟然能正常工作,虽然它的做法和之前的代码完全不同 :|

function valueToByteArray(value, bytes_length) {
    var bytes_array = [];
    while (bytes_length > 0){
        var byte = value & 0xFF;
        value >>= 8;
        bytes_length--;

        bytes_array.push(byte);
    }
    return bytes_array.reverse();
}

console.log(valueToByteArray(-2000000, 4));
<< [255, 225, 123, 128]

撰写回答