缓存对象
在 HTML 5 之前, JavaScript 操作二进制文件比较弱,各种方法效率低下,且容易产生错误。为此 HTML 5 新增了两种对象: ArrayBuffer 和 ArrayBufferView 。
使用 ArrayBuffer 对象
ArrayBuffer 对象表示一个固定长度的二进制数据的缓存区。用户不能直接存取 ArrayBuffer 缓存区内容,必须通过 ArrayBufferView 对象来读写 ArrayBuffer 缓存区的内容。
创建方法如下:
var buffer = new ArrayBuffer(32);
参数为一个无符号长整型的整数,用于设置缓存区的长度,,单位为 byte 。 ArrayBuffer 缓存区创建成功后,该缓存区内的初始数据初始化为 0 。
ArrayBuffer 对象中包含 length 属性,该属性表示缓存区的长度。
使用 ArrayBufferView 对象
HTML 5 使用 ArrayBufferView 对象以一种准确的格式来表示 ArrayBuffer 缓存区的数据。 HTML 5 不允许直接使用 ArrayBufferView 对象,而是使用 ArrayBufferView 的子类实例来读取 ArrayBuffer 缓存区的数据。
类型 | 字节长度 | 说明 |
---|---|---|
Int8Array | 1 | 8 位整数数组 |
Unit8Array | 1 | 8 位无符号整数数组 |
Unit8ClampedArray | 1 | 8 位无符号整数数组 |
Int16Array | 2 | 16 位整数数组 |
Unit16Array | 2 | 16 位无符号整数数组 |
Int32Array | 4 | 32 位整数数组 |
Unit32Array | 4 | 32 位无符号整数数组 |
Float32Array | 4 | 32 位 IEEE 浮点数数组 |
Float64Array | 8 | 32 位 IEEE 浮点数数组 |
上表中, Unit8ClampedArray 子类用于定义一种特殊的 8 位无符号整数数组,该数组的作用:代替 CanvasPixelArray 数组用于 Canvas API 中。该数组与普通的 8 位无符号整数数组的区别是,将 ArrayBuffer 缓存区的数值进行转换,内部使用箱位( clamping )算符,而不是模数( modulo )算法。
ArrayBufferView 数组的作用,可以根据同一个 ArrayBuffer 对象创建各种不同数字类型的数组。
在创建 ArrayBufferView 对象时,除了要指定 ArrayBuffer 缓存区外,还可以使用两个可选参数:
- byteOffset :为无符号长整数数值,设置开始引用位置与 ArrayBuffer 缓存区第一个字节之间的偏离值,单位为字节。提示,属性值必须为数组中单个元素的长度的倍数,省略该参数时, ArrayBuffer 对象将从 ArrayBuffer 缓存区第一个字节开始引用
- length : 为无符号长整数型数值,设置数组中元素的个数。如果省略该参数,将根据缓存区长度、 ArrayBufferView 对象开始引用的位置、每一个字符的字节长度自动计数元素个数
如果设置了 byteOffset 和 length 参数值,数组从 byteOffset 参数值指定的开始位置开始,【长度】 = 【 length 参数值所指定的元素个数】 * 【每个元素的字节长度】
。
如果忽略了 byteOffset 和 length 参数值,数组将跨越整个 ArrayBuffer 缓存区。
如果省略 length 参数值,数组将从 byteOffset 参数值指定的开始位置到 ArrayBuffer 缓存区的结束位置。
ArrayBufferView 对象包含 3 个属性∶
- buffer ∶ 只读属性,表示 ArrayBuffer 对象,返回 ArrayBufferView 对象引用的 ArrayBuffer 缓存区
- byteOffset ∶ 只读属性,表示一个无符号长整型数值,返回 ArrayBufferView 对象开始引用的位 置与 ArrayBuffer 缓存区的第一个字节之间的偏离值,单位为字节
- length ∶ 只读属性,表示一个无符号长整型数值,返回数组中元素的个数
使用 DataView 对象
除了使用 ArrayBufferView 子类外,也可以使用 DataView 类存取 ArrayBuffer 缓存区的数据。
DataView 继承于, ArrayBufferView 类,提供了一些直接存取 ArrayBuffer 缓存区中数据的方法。
创建 DataView 对象的方法如下∶
var view = new DataView(buffer, byteOffset, byteLength);
- buffer ∶ 为 ArrayBuffer 对象,表示一个 ArrayBuffer 缓存区
- byteOffset ∶ 可选参数,为无符号长整型数值,表示 DataView 对象开始引用的位置与 ArrayBuffer 缓存区第一个字节之间的偏离值,单位为字节。如果忽略该参数值,将从 ArrayBuffer 缓存区的第一个字节开始引用
- byteLength ∶ 可选参数,为无符号长整型数值,表示 DataView 对象的总字节长度
如果设置了 byteOffset 和 byteLength 参数值, DataView 对象从 byteOffset 参数值所指定的开始位置开始,长度为 byteLength 参数值所指定的总字节长度。
如果忽略了 byteOffset 和 byteLength 参数值, DataView 对象跨越整个 ArrayBuffer 缓存区。如果省略 byteLength 参数值, DataView 对象将从 byteOffset 参数所指定的开始位置到 ArrayBuffer 缓存区的结束位置。
方法 | 说明 |
---|---|
getInt8(byteOffset) | 获取指定位置的一个 8 位整数值 |
getUnit8(byteOffset) | 获取指定位置的一个 8 位无符号整数值 |
getInt16(byteOffset,littleEndian) | 获取指定位置的一个 16 位整数值 |
getUnit16(byteOffset,littleEndian) | 获取指定位置的一个 16 位无符号整数值 |
getUnit32(byteOffset,littleEndian) | 获取指定位置的一个 32 位无符号整数值 |
getFloat32(byteOffset,littleEndian) | 获取指定位置的一个 32 位浮点数值 |
setFloat64(byteOffset,littleEndian) | 获取指定位置的一个 64 位浮点数值 |
setInt8(byteOffset,value) | 获取指定位置的一个 8 位整数值 |
setUnit8(byteOffset,value) | 设置指定位置的一个 8 位无符号整数值 |
setInt16(byteOffset,value,littleEndian) | 设置指定位置的一个 16 位整数值 |
setUnit16(byteOffset,value,littleEndian) | 设置指定位置的一个 16 位无符号整数值 |
setUnit32(byteOffset,value,littleEndian) | 设置指定位置的一个 32 位无符号整数值 |
setFloat32(byteOffset,value,littleEndian) | 设置指定位置的一个 32 位浮点数值 |
setFloat64(byteOffset,value,littleEndian) | 设置指定位置的一个 64 位浮点数值 |
- byteOffset : 为一个无符号长整型整数,表示设置或读取整数所在位置与 DataView 对象对 ArrayBuffer 缓存区的开始引用位置之间间隔多少个字节
- value :位无符号对应的类型的数值,表示在指定位置进行设定的整数类型
- littleEndian : 可选参数,为布尔型,判断该整数型数值的字节序。当值为 true 时,表示以 little-endian 方式设置或读取该整数数值(低地址存放有效字节);当参数值为 false 或者忽略该参数值时,表示 big-endian 方式读取该整数数值(低地址存放最高有效字节)
window.onload = function () {
var result = document.getElementById('result');
var file = document.getElementById('file');
if (typeof FileReader == 'undefined') {
result.innerHTML = '<h1> 当前浏览器不支持 FileReader 对象 </h1>';
file.setAttribute('disabled', 'disabled');
}
};
function file_onchange() {
var file = document.getElementById('file').files[0];
if (!/image\/\w+/.test(file.type)) {
alert(' 请选择一个图像文件! ');
return;
}
var slice = file.slice(0, 4);
var reader = new FileReader();
reader.readAsArrayBuffer(slice);
var type;
reader.onload = function (e) {
var buffer = this.result;
var view = new DataView(buffer);
var magic = view.getInt32(0, false);
if (magic < 0) magic = magic + 0x100000000;
magic = magic.toString(16).toUpperCase();
if (magic.indexOf('FFD8FF') >= 0) type = 'jpg 文件 ';
if (magic.indexOf('89504E47') >= 0) type = 'png 文件 ';
if (magic.indexOf('47494638') >= 0) type = 'gif 文件 ';
if (magic.indexOf('49492A00') >= 0) type = 'tif 文件 ';
if (magic.indexOf('424D') >= 0) type = 'bmp 文件 ';
document.getElementById('result').innerHTML = ' 文件类型为: ' + type;
};
}