ArrayBuffer
对象、TypedArray
视图和DataView
视图是 JavaScript 操作二进制数据的一个接口。它们都是以数组的语法处理二进制数据,所以统称为二进制数组。
二进制数组由三类对象组成。
(1)ArrayBuffer
对象:
代表内存之中的一段二进制数据,可以通过“视图”进行操作。“视图”部署了数组接口,这意味着,可以用数组的方法操作内存。
(2)TypedArray
视图:
共包括 9 种类型的视图,比如Uint8Array
(无符号 8 位整数)数组视图, Int16Array
(16 位整数)数组视图, Float32Array
(32 位浮点数)数组视图等等。
(3)DataView
视图:
可以自定义复合格式的视图,比如第一个字节是 Uint8(无符号 8 位整数)、第二、三个字节是 Int16(16 位整数)、第四个字节开始是 Float32(32 位浮点数)等等,此外还可以自定义字节序。
简单说,ArrayBuffer
对象代表原始的二进制数据,TypedArray
视图用来读写简单类型的二进制数据,DataView
视图用来读写复杂类型的二进制数据。
TypedArray
视图支持的数据类型一共有 9 种(DataView
视图支持除Uint8C
以外的其他 8 种)。
一、arrayBuffer和new Blob
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<input type="file" id="file"/>
<script>
/* //上传文件 后端返回的是buffer 前端操作excel
// 前端最常用的是Blob对象() binary large object 是不可变的。
// File 基于Blob的。
// 1.实现前端下载html。
let str='<h1>hello world</h1>';
const blob=new Blob([str],{
type:'text/html'
})
// 前端下载用a标签。
// 通过blob产生一个临时访问的链接
let a=document.createElement('a');
a.innerHTML='下载';
a.setAttribute('download','a.html');
a.href=URL.createObjectURL(blob);
document.body.appendChild(a); */
// 通过字符串构建一个blob。
//2) webgl
// 二进制类型 不能直接修改arrayBuffer。
// Blob 是传输的整体文件。
let arrayBuffer=new ArrayBuffer(10);
console.log(arrayBuffer);
let blob=new Blob([arrayBuffer]);
console.log(blob);
// blob 代表的是传输的整体文件。
// FileReader 文件读取器。
let fileReader=new FileReader();
fileReader.onload=function (){
console.log(fileReader.result);
}
// 尽量使用createObjectURL(blob) 来产生url。
fileReader.readAsDataURL(blob); // 转化成base64
// fileReader 预览功能。
// file 核心就是一个blob 只是在这个基础上做了扩展。
file.addEventListener('change',(e)=>{
//1) 第一种方案
let file=e.target.files[0];
let fileReader=new FileReader();
fileReader.onload=function (){
let img=document.createElement('img');
img.src=fileReader.result;
document.body.appendChild(img);
}
// 尽量使用createObjectURL(blob) 来产生url。
fileReader.readAsDataURL(file); // 转化成base64
// 2)第二种方案
// 一般选择下面的方案。
/* let r=URL.createObjectURL(file);
console.log(r);
let img=document.createElement('img');
img.src=r;
document.body.appendChild(img); */
//URL.revokeObjectURL(r); // 释放掉URL
})
// arrayBuffer 浏览器中的二进制
// 通过视图来进行访问。
let buffer =new ArrayBuffer(4) //创造4个字节。
// TypeArray 描述底层的二进制数据。 int8Array uint8Array
// TypeArray 对象描述了一个底层的二进制数据缓冲区 的类视图。
let x1=new Uint8Array(buffer);
x1[0]=1;
console.log(x1);
let x2=new Uint16Array(buffer);
// DateView 也可以通过一个接口去改
// buffer 是表示内存的。
// 如果将字符串转化成arrayBuffer(前端) == buffer (后端)
function stringToArrayBuffer(str){ //后端3个字节。 前端用utf16 两个字节来表示。
let buffer =new ArrayBuffer(str.length*2);
let view=new Uint16Array(buffer);
for(let i=0;i<str.length;i++){
view[i]=str.charCodeAt(i);
}
return buffer;
}
console.log(ArrayBufferToString(stringToArrayBuffer('你好')))
// arrayBuffer 没有toString的方法。
function ArrayBufferToString(buf){
return String.fromCharCode(...new Uint16Array(buf));
}
//前端解析excel
// 发送一个请求,服务端返回一个文件 实现下载即可。
function request(url,method='get'){
return new Promise((resolve,reject)=>{
let xhr=new XMLHttpRequest();
xhr.open(method,url,true);
xhr.responseType="arraybuffer";
xhr.onload=function(){
resolve(xhr.response);
}
xhr.send();
})
}
request('/download').then(arraybuffer=>{
let b=new Blob([arraybuffer]); //直接将arrayBuffer封装成文件。
console.log(b);
let blobUrl=URL.createObjectURL(b);
let a=document.createElement('a');
a.href=blobUrl;
a.download="a.pdf";
document.body.appendChild(a);
a.click();
a.remove();
URL.revokeObjectURL(blobUrl);
})
</script>
</body>
</html>
二、Buffer的使用
/**
* 1、三种声明方式 代表的是内存 大小是不能发生变化的。
* 2、buffer 可以通过数字 通过字符串 通过数组 来声明,都是固定大小的
*
* 3、常用的声明:长度和内容来声明。
*/
let buffer=Buffer.alloc(10);
console.log(buffer);
// 16进制 最大就是ff
let buffer1=Buffer.from('数据'); // uft8 一个汉字是有3个字节组成。
console.log(buffer1.toString('base64'));
let buffer2=Buffer.from([0xe6,0x95,0xb0]);
console.log(buffer2);
// Buffer 可以和字符串任意的转化
// 怎么转化base 64
// base64 以前是6个 现在是8个。 可以放到任何url的地方,不能转化大图片。
// base64 核心:编码操作, 1个汉字3个字节 24位===> 4x6的格式.
let code=Buffer.from('数');
console.log(0xe6.toString(2),0x95.toString(2),0xb0.toString(2)); //0xe6 0x95 0xb0
// 00111001 00101001 00010110 00110000
// 取值范围 0-63 所以只能叫base64
// 取值表。
let str='ABCDEFGHIJKLMNOPQRSTUVWXYZ';
str+='ABCDEFGHIJKLMNOPQRSTUVWXYZ'.toLowerCase();
str+='0123456789+/';
console.log(parseInt('00111001',2));
console.log(parseInt('00101001',2));
console.log(parseInt('00010110',2));
console.log(parseInt('00110000',2));
console.log(str[57]+str[41]+str[22]+str[48]);
// 前端的二进制
三、编码问题
## 编码问题
- ASCII 编码 目前定义了128个字符。
- 一个字节多少位 8位 位里面存的是二进制。二进制逢二进一
- parseInt('1011',2); // 二进制
- 0xff 16进制的 255
- 两个字节来表示一个汉字 GB2312 两个字节用来表示中文
- 255*255 = 65025
- GBK 融入了一些生僻汉字
- GB18030 融入了少数字符集
- unicode 只是一个字符集而已 做了一个编码 100多万个字符
- unf8 是unicode 的一种存储方式。可变字符长度 字母1个字节 汉字3个字节
- uft16 / ucs-2 js内部就是使用的utf-8 两个字节表示一个字符 不管是字母还是汉字。
- node中默认只支持uft-8格式的。
- 任意进制转化为10进制 parseInt()
- 10 进制转化为其他进制 toString();
## buffer
- 后端操作数据(二进制类型) buffer就是用来表示这些二进制
- fs.readFile(); (默认操作文件) 都是二进制类型。buffer他是16进制的。