2016-11-24 115 views
0

我想用ArrayBuffer处理二进制数据。如果原始ArrayBuffer如下所示:Endianness安全复制二进制数据

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方法没有预谋,所以我做到了我自己。这不是问题,但考虑到endianness真的让我发疯。

前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?或者我应该忘记排序?任何建议将非常感激。

+0

您尚未显示服务器用于从其接收的二进制数据中读取的代码? – Bergi

回答

1

对于因为他们没有字节序没关系字节,但如果你不是一个字节的更宽的数据(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 
} 

结果然后可以使用所述小端标志的各种方法的数据视图中。

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

1

由于您没有使用带有索引访问的​​,而是使用DataView及其setUint16 method,所以字节序总是默认为big-endian。