Buffer的应用

一.编码的发展

一个字节由8个位组成,gbk中一个汉字2个字节,utf8中一个汉字3个字节

  • ASCII编码
  • GB2312
  • GBK
  • GB18030
  • Unicode
  • UTF-8

Node中不支持GBK编码,我们需要将GBK转为UTF8编码

var iconv = require('iconv-lite');
function readGBKText(pathname) {
    var bin = fs.readFileSync(pathname);
    return iconv.decode(bin, 'gbk');
}
1
2
3
4
5

二.进制转化

//把任意进制转成十进制
console.log(parseInt('20',10));//20
console.log(parseInt('11',2));//3
console.log(parseInt('20',16));//32
//把十进制转成任意进制
console.log((3).toString(2));//11
console.log(3..toString(2));//11
console.log((77).toString(8));//115 
console.log((77).toString(16));//4d 
console.log((17).toString(8));//21
1
2
3
4
5
6
7
8
9
10

三.Buffer的应用

1.定义buffer的三种方式

let buf1 = Buffer.alloc(6);
let buf2 = Buffer.from('珠峰');
let buf3 = Buffer.from([65,66,67]);
1
2
3

2.buffer中常用的方法

  • buff.toString()
  • buff.fill()
  • buff.slice()
  • buff.copy
  • Buffer.concat()
  • Buffer.isBuffer()
  • indexOf

copy方法的实现

Buffer.prototype.copy = function(targetBuffer,targetStart,sourceStart,sourceEnd){
  for(let i=sourceStart;i<sourceEnd;i++){
    targetBuffer[targetStart++]=this[i];
  }
}
1
2
3
4
5

concat方法的实现

Buffer.concat = function(bufferList,len=bufferList.reduce((a,b)=>a+b.length,0)){
    let buffer = Buffer.alloc(len);
    let offset = 0;
    bufferList.forEach(buf=>{
        buf.copy(buffer,offset);
        offset += buf.length;
    })
    return buffer;
}
1
2
3
4
5
6
7
8
9

封装buffer.split方法

Buffer.prototype.split = function(sep){ // slice + indexOf = split
    let arr = [];
    let len = Buffer.from(sep).length; //  分割符号的长度
    let offset = 0;
    let current;
    while(-1!=(current = this.indexOf(sep,offset))){
        // 找到的位置 加上偏移量
        arr.push(this.slice(offset,current));
        offset = current+len;
    }
    arr.push(this.slice(offset));
    return arr;
}
1
2
3
4
5
6
7
8
9
10
11
12
13

3.base64转化

const CHARTS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
function transfer(str){
  let buf = Buffer.from(str);
  let result = '';
  for(let b of buf){
      result += b.toString(2);
  }
  return result.match(/(\d{6})/g).map(val=>parseInt(val,2)).map(val=>CHARTS[val]).join('');
}
let r = transfer('a');
console.log(r);
1
2
3
4
5
6
7
8
9
10
11

四.前端二进制对象

前端最常用的Blob对象 binary large object (是不可变的) 代表的是文件类型

1.前端下载html功能

let str = `<h1>hello world</h1>`;
const blob = new Blob([str], {
     type: 'text/html'
});
let a = document.createElement('a');
a.setAttribute('download', 'a.html');
a.href = URL.createObjectURL(blob);
document.body.appendChild(a);
1
2
3
4
5
6
7
8

2.前端文件预览

使用fileReader来实现

file.addEventListener('change', (e) => {
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)
}
fileReader.readAsDataURL(file);
1
2
3
4
5
6
7
8
9

createObjectURL来实现

let r = URL.createObjectURL(file);
let img = document.createElement('img');
img.src = r;
document.body.appendChild(img)
URL.revokeObjectURL(r);
1
2
3
4
5

3.arrayBuffer(浏览器中的二进制)

let buffer = new ArrayBuffer(4);// 创造4个字节
let x1 = new Uint8Array(buffer);
x1[0] = 1; // 00000000 00000000 11111111 00000001
x1[1] = 255;
console.log(x1); // [1,255,0,0]

let x2 = new Uint16Array(buffer); 
console.log(x2) // [65281,0]

let x3 = new Uint32Array(buffer);
console.log(x3) // [65281]
1
2
3
4
5
6
7
8
9
10
11

arraybuffer不能被直接修改

4.字符串和arrayBuffer转化

字符串转化成arrayBuffer

function stringToArrayBuffer(str) { // 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
}
1
2
3
4
5
6
7
8

arrayBuffer转化成字符串

function ArrayBufferToString(buf) {
    return String.fromCharCode(...new Uint16Array(buf))
}
1
2
3

5.responseType:'arrayBuffer'

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]); 
    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)
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

服务端代码

const express = require('express');
const app = express();
app.listen(4444);
app.use(express.static(__dirname));
app.get('/download', (req, res) => {
    res.download('a.pdf');
})
1
2
3
4
5
6
7