2016-11-24 99 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。