2016-11-24 15 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의 길이는 Uint16Array가 20입니다. 추가하지 않고 여분의 바이너리 데이터를 앞에두고 싶습니다. 내가 아는 한, ArrayBuffer의 방법과 같은 더 prepending이가없는

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

, 그래서 내가 직접했다 :의 내가 같이 UINT8의 5 바이트를 씁니다한다고 가정 해 봅시다. 이것은 중요하지 않았지만, 엔디안이 정말로 나를 미치게 만들었다 고 생각하면.

처음 5 바이트의 데이터가 생성되었으므로 수동으로 엔디안을 설정할 수는 있지만 원본 데이터는 외부에서 가져 오므로 데이터는 Little Endian과 Big Endian이 될 수 있습니다.

Node.js 및 웹 브라우저 용 바이너리 데이터 모듈을 만들고 있습니다. 기본 사용법은이 모듈을 사용하여 웹 브라우저에서 여분의 바이너리 데이터를 선행하여 브라우저에서 서버로 보낸 다음 서버로 보냅니다. 이 모듈에서이 바이너리 데이터를 읽고, prepended와 orignal로 나눕니다.

그러나 브라우저에서 리틀 엔디안을 사용하는 클라이언트 컴퓨터와 빅 엔디안을 사용하는 서버가 서로 다른 엔디안을 가지고 있기 때문에 원본 데이터가 올바르게 읽히지 않을 수 있습니다.

원본 데이터를 이와 같이 새로운 바이너리 데이터에 추가하려고합니다. 새로운 바이너리 데이터는 0 ~ 5 바이트에서 5 바이트의 데이터가 서로 다릅니다. 그래서 5 바이트 오프셋 후 작성해야합니다. 서버와 클라이언트가 모두 동일한 CPU를 사용하기 때문에 내 로컬 컴퓨터에

// 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)); 
} 

테스트는 괜찮지 만, 서로 다른 엔디안이있는 경우 실생활에서,이 모듈이 제대로 작동하지 않습니다.

ArrayBuffer & DataView로 바이너리 데이터를 복사하는 엔디안 방식이 안전한가요? 아니면 엔딩을 잊어 버려야합니까? 어떤 충고라도 매우 감사 할 것입니다.

+0

서버에서받은 바이너리 데이터를 읽는 데 사용하는 코드가 아직 표시되지 않았습니까? – Bergi

답변

1

엔디안이 없기 때문에 바이트는 중요하지 않지만 바이트 (16/32 비트 등)보다 넓은 데이터를 얻으면 미리 엔디안을 알아야합니다. 원래 엔디안을 감지합니다 (데이터에 따라 추측 할 수 있지만 ...).

대부분의 경우 바이트 스트림은 기본적으로 빅 엔디안 인 네트워크 순서로되어 있으며 DataView의 기본값은 무엇입니까?

그러나 클라이언트에 데이터를 보내기 전에 테스트 기능을 구현하는 것이 좋습니다. 예를 들어 isLittleEndian() 함수를 사용하여 클라이언트에서 서버를 호출하면 서버가 0xff00과 같은 16 비트 값을 다시 보내도록 트리거합니다. 바이트가 수신 주문하는 그런 시험 ​​- 같은 :

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 아키텍처/엔디안이 아닐 수 있습니다 (리틀 엔디안 서버는 여전히 빅 엔디안/네트워크 주문에서 데이터를 보낼 수 있음).

1

인덱스 된 액세스를 사용하는 Uint16Array이 아니기 때문에 DataViewsetUint16 method이 사용되므로 endianness는 항상 big-endian으로 기본 설정됩니다.