ArrayBuffer是所有视图的通用字节数组。类型化数组只是意味着数组上有一个关联类型,例如uint8,int16等。所有的Uin8Array,Int32Array等都是在ArrayBuffer之上的视图,以便使用它们表示的类型进行读写。 (U)int8数组没有字节顺序,因为它们是单个字节(即无需重新排序)。字节需要表示更广泛的内容,如(u)int-16或-32(在ES7之前不支持64位整数,但确实有32位和64位IEEE浮点数)。
任何您通过视图读取或写入的内容都会返回到它们指向的同一个ArrayBuffer中 - 您甚至可以为同一个缓冲区创建多个视图。
要交换顺序为16位则可以使用Uint16Array视图和交换手动简单地读取ArrayBuffer:
var buffer16 = new Uint16Array(buffer); // use same buffer as for the Uin8Array view
for(var i = 0, v; i < buffer16.length; i++) {
v = buffer16[i];
buffer16[i] = ((v & 0xff) << 8) | ((v & 0xff00) >>> 8); // mask and shift the two bytes
}
如果你有一个8位的视图相同的缓冲液你现在可以读取单个字节与新的订单。
对于32位,你会怎么做:
var buffer32 = new Uint32Array(buffer);
for(var i = 0, v; i < buffer32.length; i++) {
v = buffer32[i];
buffer32[i] = ((v & 0xff) << 24) | // mask, move byte 0 to 3
((v & 0xff00) << 8) | // mask, move byte 1 to 2
((v & 0xff0000) >>> 8) | // mask, move byte 2 to 1 unsigned
((v & 0xff000000) >>> 24); // mask, move byte 3 to 0 unsigned
}
然而,这些意见需要一致的缓冲器意味着缓冲区的长度(U)INT16必须为偶数长度保持一致,而32位必须是对齐到4个字节。
如果缓冲器不是,则可以改为使用一个数据视图阅读和在一些性能为代价写任何长度,在任何位置:
var view = new DataView(buffer);
var alignedLength = ((buffer.length/2)|0) * 2; // aligned to 16-bit
// 16-bit
for(var i = 0, v; i < alignedLength; i += 2) {
v = view.getUint16(i, false); // read as big-endian
view.setUint16(i, v, true); // write as little-endian
}
和32位使用getUint32/setUint32代替,注意,如果ArrayBuffer未对齐到2或4个字节(通常您会对齐buffer.length并在循环中使用它,如图所示,请使用4为32位)。
如果源缓冲区包含混合长度(例如,如果它包含原始二进制文件),则必须根据文件格式规范解析每个值。为此,请使用DataView。
例子
var buffer = new ArrayBuffer(4),
b8 = new Uint8Array(buffer),
b16 = new Uint16Array(buffer),
b32 = new Uint32Array(buffer),
view = new DataView(buffer);
setData();
show("Original unsigned big-endian");
// swap the value using 16-bit array
for(var i = 0, v; i < b16.length; i++) {
v = b16[i];
b16[i] = ((v & 0xff) << 8) | ((v & 0xff00) >>> 8);
}
show("Byte-order swapped 16-bits");
setData();
for(var i = 0, v; i < b32.length; i++) {
v = b32[i];
b32[i] = ((v & 0xff) << 24) |
((v & 0xff00) << 8) |
((v & 0xff0000) >>> 8) |
((v & 0xff000000) >>> 24);
}
show("Byte-order swapped 32-bits");
setData();
for(var i = 0, v; i < buffer.byteLength; i += 2) {
v = view.getUint16(i, false); // big-endian
view.setUint16(i, v, true); // little-endian
}
show("Byte-order swapped 16-bit using DataView");
setData();
for(var i = 0, v; i < buffer.byteLength; i += 4) {
v = view.getUint32(i, false); // big-endian
view.setUint32(i, v, true); // little-endian
}
show("Byte-order swapped 32-bit using DataView");
function valToHex(v) {
return (v>>>0).toString(16)
}
function setData() {
b8[0] = 255; // "network" order/big.endian 0xff804020
b8[1] = 128;
b8[2] = 64;
b8[3] = 32;
}
function show(pre) {
document.write(pre + ": ");
document.write("0x" + valToHex(b8[0]));
document.write(valToHex(b8[1]));
document.write(valToHex(b8[2]));
document.write(valToHex(b8[3]) + "<br>");
}
body {font:16px monospace}
来源
2015-06-05 22:44:57
K3N
笑我真的没有想到。当然,Uint8s只是单个字节。感谢您的详细和彻底的答复。 – user2871915