자바 스크립트 유형 배열 및 엔디안
WebGL을 사용하여 바이너리 인코딩 된 메시 파일을 렌더링하고 있습니다. 바이너리 파일은 big-endian 형식으로 작성됩니다 (16 진수 편집기에서 파일을 열거 나 fiddler를 사용하여 네트워크 트래픽을 확인하여 확인할 수 있습니다). Float32Array 또는 Int32Array를 사용하여 이진 응답을 읽으려고하면 이진이 리틀 엔디안으로 해석되고 내 값이 잘못되었습니다.
// Interpret first 32bits in buffer as an int
var wrongValue = new Int32Array(binaryArrayBuffer)[0];
http://www.khronos.org/registry/typedarray/specs/latest/ 에서 형식화 된 배열의 기본 엔디안에 대한 참조를 찾을 수 없으므로 거래가 무엇인지 궁금합니다. 형식화 된 배열을 사용하여 읽을 때 모든 이진 데이터가 리틀 엔디안이어야한다고 가정해야합니까?
문제를 해결하기 위해 DataView 개체 (이전 링크에서 설명)를 사용하고 다음을 호출 할 수 있습니다.
// Interpret first 32bits in buffer as an int
var correctValue = new DataView(binaryArrayBuffer).getInt32(0);
"getInt32"와 같은 DataView 함수는 기본적으로 빅 엔디안 값을 읽습니다.
(참고 : Google Chrome 15 및 Firefox 8을 사용하여 테스트했으며 둘 다 동일한 방식으로 작동합니다.)
슬프게도 현재 동작은 엔디안이 기본 하드웨어의 동작이라는 것입니다. 거의 모든 데스크톱 컴퓨터가 x86이므로 리틀 엔디안을 의미합니다. 대부분의 ARM OS는 리틀 엔디안 모드를 사용합니다 (ARM 프로세서는 바이 엔디안이므로 둘 중 하나에서 작동 할 수 있음).
이것이 다소 슬픈 이유는 자신의 코드가 빅 엔디안 하드웨어에서 작동하는지 여부를 테스트하는 사람이 거의 없다는 것을 의미하고, 수행하는 작업을 손상 시키며, 전체 웹 플랫폼이 구현 및 플랫폼 전반에 걸쳐 균일하게 작동하는 코드를 중심으로 설계되었다는 사실을 의미합니다. 이것이 깨지는.
참고로 다음 자바 스크립트 함수를 사용하여 컴퓨터의 엔디안을 확인할 수 있습니다. 그런 다음 적절하게 형식이 지정된 파일을 클라이언트에 전달할 수 있습니다 (서버에 파일의 두 가지 버전, 빅 엔디안 및 리틀 엔디안을 저장할 수 있음).
function checkEndian() {
var arrayBuffer = new ArrayBuffer(2);
var uint8Array = new Uint8Array(arrayBuffer);
var uint16array = new Uint16Array(arrayBuffer);
uint8Array[0] = 0xAA; // set first byte
uint8Array[1] = 0xBB; // set second byte
if(uint16array[0] === 0xBBAA) return "little endian";
if(uint16array[0] === 0xAABB) return "big endian";
else throw new Error("Something crazy just happened");
}
귀하의 경우에는 리틀 엔디안으로 파일을 다시 생성하거나 리틀 엔디안으로 만들기 위해 전체 데이터 구조를 실행해야 할 것입니다. 위의 방법을 비틀어 사용하면 즉시 엔디안을 바꿀 수 있습니다 (실제로 권장되지는 않으며 전체 구조가 꽉 찬 유형 인 경우에만 의미가 있습니다. 실제로 필요에 따라 바이트를 교체하는 스텁 함수를 만들 수 있습니다).
function swapBytes(buf, size) {
var bytes = new Uint8Array(buf);
var len = bytes.length;
var holder;
if (size == 'WORD') {
// 16 bit
for (var i = 0; i<len; i+=2) {
holder = bytes[i];
bytes[i] = bytes[i+1];
bytes[i+1] = holder;
}
} else if (size == 'DWORD') {
// 32 bit
for (var i = 0; i<len; i+=4) {
holder = bytes[i];
bytes[i] = bytes[i+3];
bytes[i+3] = holder;
holder = bytes[i+1];
bytes[i+1] = bytes[i+2];
bytes[i+2] = holder;
}
}
}
여기 http://www.khronos.org/registry/typedarray/specs/latest/ (사양이 완전히 구현 된 경우)에서 가져 오면 다음을 사용할 수 있습니다.
new DataView(binaryArrayBuffer).getInt32(0, true) // For little endian
new DataView(binaryArrayBuffer).getInt32(0, false) // For big endian
However, if you can't use those method because they aren't implemented, you can always check the file's magic value (almost every format has a magic value) on the header to see if you need to invert it according to your endiannes.
Also, you can save endiannes-specific files on your server and use them accordingly to the detected host endiannes.
The other answers seem a bit outdated to me, so here's a link to the latest spec:
http://www.khronos.org/registry/typedarray/specs/latest/#2.1
In particular:
The typed array view types operate with the endianness of the host computer.
The DataView type operates upon data with a specified endianness (big-endian or little-endian).
So if you want to read/write data in Big Endian (Network Byte Order), see: http://www.khronos.org/registry/typedarray/specs/latest/#DATAVIEW
// For multi-byte values, the optional littleEndian argument
// indicates whether a big-endian or little-endian value should be
// read. If false or undefined, a big-endian value is read.
Quick way to check endianness
/** @returns {Boolean} true if system is big endian */
function isBigEndian() {
const array = new Uint8Array(4);
const view = new Uint32Array(array.buffer);
return !((view[0] = 1) & array[0]);
}
How it works:
- an array of 4 bytes is created;
- a 32-bit view wraps that array;
view[0] = 1
sets the array to hold 32-bit value 1;- now comes the important part: if system is big endian, that 1 is being hold by the rightmost byte (little comes last); if it is little endian, it is the leftmost byte that stores it (little comes first). So doing a bitwise AND with the leftmost byte returns false if the machine is big endian;
- the function finally converts it to a boolean by applying the
!
operator to the result of the&
operation, while also inverting it so that it returns true for big endian.
ReferenceURL : https://stackoverflow.com/questions/7869752/javascript-typed-arrays-and-endianness
'Programing' 카테고리의 다른 글
오류 메시지“응용 프로그램을 설치하거나 실행할 수 없습니다. (0) | 2020.12.29 |
---|---|
설치된 MS-Office 버전을 어떻게 감지합니까? (0) | 2020.12.29 |
mysql의 테이블에서 모든 레코드 삭제 (0) | 2020.12.29 |
WordPress 설치의 wp_options 테이블에서 과도 현상을 제거 할 수 있습니까? (0) | 2020.12.29 |
숨겨진 필드를 카피 바라로 채우는 방법? (0) | 2020.12.29 |