跳到主要内容

缓存对象

在 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 缓存区的数据。

类型字节长度说明
Int8Array18 位整数数组
Unit8Array18 位无符号整数数组
Unit8ClampedArray18 位无符号整数数组
Int16Array216 位整数数组
Unit16Array216 位无符号整数数组
Int32Array432 位整数数组
Unit32Array432 位无符号整数数组
Float32Array432 位 IEEE 浮点数数组
Float64Array832 位 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;
};
}