1 概述
javascript中的二进制操作,主要讨论的是浏览器中的blob,ArrayBuffer,DataView,TypeArray的操作。
2 ArrayBuffer
var a = new ArrayBuffer(8)
console.log(a,a.byteLength);
var b = a.slice(0,4);
console.log(b,b.byteLength);
ArrayBuffer的操作只有以上三种,建立一个固定长度的arrayBuffer,获取arraybuffer的长度以及将一个arraybuffer取出一部分。要注意的是,为什么要arraybuffer要这么设计。因为,直接用js的array操作二进制时,array需要支持动态扩容和缩容,所以内部实现是相当低效的。arraybuffer相当于一个固定长度的array,它不需要考虑动态扩容和缩容,内部实现效率更高。
3 TypeArray
Int8Array
Uint8Array
Uint8ClampedArray
Int16Array
Uint16Array
Int32Array
Uint32Array
Float32Array
Float64Array
TypeArray是以上的array的总称,它的意思将二进制的arrayBuffer看成是单一类型的数组,然后在这个类型化的数组上进行存取操作。
var a = new ArrayBuffer(8);
console.log(a,a.byteLength);
var uint8array=new Uint8Array(a);
uint8array[0]=01;
uint8array[1]=02;
uint8array[2]=03;
uint8array[3]=04;
console.log(uint8array,uint8array[2],uint8array.length);
var uint8array2 = uint8array.subarray(1,3);
uint8array2[0] = 07;
uint8array2[1] = 08;
console.log(uint8array,uint8array.length);
console.log(uint8array2,uint8array2.length);
console.log(uint8array.buffer,uint8array2.buffer);
var uint8array3 = uint8array.slice(1,3);
uint8array3[0] = 09;
uint8array3[1] = 10;
console.log(uint8array,uint8array.length);
console.log(uint8array3,uint8array3.length);
console.log(uint8array.buffer,uint8array3.buffer);
以uint8array为例子,将arraybuffer存进去,那么uint8array就能作为arraybuffer的视图进行存取操作。要注意的是,subarray与slice的区别。subarray是引用原来的arraybuffer的新视图,slice是复制原来的arraybuffer的新视图,它们是不一样的。
4 DataView
var a = new ArrayBuffer(8);
console.log(a,a.byteLength);
var uint8array=new Uint8Array(a);
console.log(uint8array);
var dataview = new DataView(a);
dataview.setUint8(0,11);
dataview.setUint16(1,12);
dataview.setUint32(3,13);
console.log(dataview,dataview.byteLength);
console.log(uint8array);
var output = "";
for( var i = 0 ; i != dataview.byteLength;i++ ){
var single = dataview.getUint8(i);
output += single+",";
}
console.log(output);
TypeArray是将arraybuffer看成是单一类型的二进制数据,那么DataView是将arraybuffer看成是混合类型的二进制数据。它可以通过getXXX和setXXX对arraybuffer进行存取的操作。要注意的是,对于多字节类型,它同时支持大端和小端的存取操作,默认为大端操作。
5 Blob
blob与arraybuffer相当相似,唯一不同的是,它是不可修改的,它不像arraybuffer能提供视图来修改内部数据,blob一旦创建以后就是不可修改的,一般用来存放图片,文件的数据。
function output(blob){
var reader = new FileReader();
reader.onload = function (e) {
var buf = new Uint8Array(reader.result);
console.info(buf);
}
reader.readAsArrayBuffer(blob);
}
var blob = new Blob(["abcdefg"], {type : 'text/html'});
output(blob);
var buffer2 = new ArrayBuffer(8);
var blob2 = new Blob([buffer2]);
output(blob2);
var uint8array = new Uint8Array(buffer2);
console.log(uint8array);
uint8array[0] = 7;
console.log(uint8array);
output(blob2);
使用arraybuffer创建blob2以后,即使arraybuffer修改了,blob2也是原来的数据,这表明blob2是immutable的。另外,注意一下blob的读取方式,是通过reader进行的。
6 Buffer
function newBuffer(){
var buffer = Buffer.from("Hello World");
for( var i = 0 ; i != buffer.byteLength ;i ++ ){
console.log(buffer[i]);
}
buffer[0] = "M".charCodeAt(0);
var buffer2 = Buffer.from("CCDXXX");
var buffer3 = Buffer.concat([buffer,buffer2]);
return buffer3.slice(0,15);
}
function toString(buffer){
return buffer.toString('utf-8');
}
function toArrayBuffer(buffer){
return buffer.buffer.slice(buffer.byteOffset,buffer.byteOffset+buffer.byteLength);
}
function toUint8Array(buffer){
return new Uint8Array(buffer.buffer,buffer.byteOffset,buffer.byteLength);
}
var buffer = newBuffer();
console.log(toString(buffer));
console.log(toArrayBuffer(buffer));
console.log(toUint8Array(buffer));
buffer是node环境下操作二进制的类型,它类比于ArrayBuffer,但是比ArrayBuffer的功能更强大,除了有ArrayBuffer的创建,获取长度,截取,和读写某个位置的数据外,它提供了concat,copy,compare,toString的工具函数,方便了我们操作二进制的数据。同样地,它也能转换到ArrayBuffer,TypeArray,DataaView和Blob上。
7 总结
挺简单的,但也是容易忽略的小知识。
- 本文作者: fishedee
- 版权声明: 本博客所有文章均采用 CC BY-NC-SA 3.0 CN 许可协议,转载必须注明出处!