javascript - 字节序安全复制二进制数据

标签 javascript endianness arraybuffer typed-arrays

我正在尝试使用 ArrayBuffer 操作二进制数据。如果原始 ArrayBuffer 看起来像这样:

var buffer = new ArrayBuffer(40);
var dv = new DataView(buffer);

var num = 0;
for(var i = 0; i < 40; i+=2) {
    dv.setUint16(i, num++);
}

然后ArrayBuffer有20长度的Uint16Array。我想在前面添加额外的二进制数据,而不是附加。假设我想在前面添加 5 个字节的 Uint8,如下所示:

ArrayBuffer[0] = 10;
ArrayBuffer[1] = 20;
ArrayBuffer[2] = 30;
ArrayBuffer[3] = 40;
ArrayBuffer[4] = 50;
ArrayBuffer[5 ~ 25] = Original Data

据我所知,ArrayBuffer中没有类似prepending的方法,所以我自己做了。这并不重要,但考虑字节序确实让我发疯。

前5个字节的数据是我自己生成的,所以我可以手动设置字节序,但原始数据来自外部,所以数据可能是Little Endian和Big Endian。

我正在为 Node.js 和 Web 浏览器制作某种二进制数据模块,两者都可以使用,基本用法是使用此模块从 Web 浏览器添加额外的二进制数据,浏览器将其发送到服务器,然后服务器读取该二进制数据也来自该模块,并分为前置数据和原始数据。

但问题是,如果浏览器,我的意思是客户端计算机使用小端,而服务器使用大端,原始数据可能无法正确读取,因为它们具有不同的端序。

我将原始数据附加到新的二进制数据中,如下所示。新的二进制数据在0~5字节处有不同的5字节数据。所以我必须在5个字节偏移之后写入。

// write rest of data
var newBuffer = new ArrayBuffer(5 + origBuffer.byteLength);
var ndv = new DataView(newBuffer);
var dv = new DataView(origBuffer);    

for(var i = 0; i < origBuffer.byteLength; i++) {
    var offset = 5 + i;
    ndv.setUint8(offset, dv.getUint8(i));
}

在我的本地机器上测试没问题,因为服务器和客户端都使用相同的CPU,但在现实生活中,如果它们具有不同的字节序,则该模块将无法正常工作。

是否有一种字节顺序安全的方法来使用 ArrayBuffer 和 DataView 复制二进制数据?或者我应该忘记字节顺序?任何建议将非常感激。

最佳答案

对于字节来说,这并不重要,因为它们没有字节顺序,但如果您获得的数据比字节宽(16/32位等),您必须提前知道字节顺序,因为无法检测到原始的字节顺序(您可以根据数据进行一些猜测,但是......)。

在大多数情况下,字节流采用所谓的网络顺序,基本上是大尾数法,也是 DataView 默认的。

但是,我建议在向客户端发送任何数据之前实现测试功能。例如,使用 isLittleEndian() 函数从客户端调用服务器,该函数会触发服务器发回 16 位值,例如 0xff00。然后测试接收字节的顺序 - 类似于:

function isLittleEndian(callback) {  // callback as request will be async
  // get 0xff00 from server as 2 byte ArrayBuffer here somehow...
  var test = new Uint8Array(arraybufferFromServer);
  callback({isLittleEndian: !test[0]}); // will be 0x00ff as little-endian
}

然后可以将结果与 DataView 一起使用,并为各种方法使用小端标志。

请注意,这适用于数据流,而不一定适用于服务器的 CPU 架构/字节顺序(小端服务器仍然(并且很可能)以大端/网络顺序发送数据)。

关于javascript - 字节序安全复制二进制数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40787793/

相关文章:

javascript - 在 Javascript 中对两个 ArrayBuffers 中的元素对进行按位运算的最有效方法

javascript - jquery事件命名空间冒泡问题

c# - 如何将 float 组转换为 byte[] 并返回?

javascript - 如何更改全日历月份中的天数

将大端 MIPS 转换为 C

c - 这个程序在 C 中的输出解释?

javascript - 将 HTTP 响应类型设置为 arraybuffer

java - ArrayBuffer 在内存中是如何工作的?

javascript - Canvas :在绘制的图像和剪辑之间插入渐变矩形

javascript - IE6 不会承认动态添加内容的新样式含义