8. Buffer的应用

图片来源网络

一. buffer是什么?

Node中,应用需要处理网络协议、操作数据库、处理图片、接收上传文件等,在网络流和文件的操作中,还要处理大量二进制数据,JavaScript自有的字符串远远不能满足这些需求,于是Buffer对象应运而生。

Buffer作为存在于全局对象上,无需引入模块即可使用,你绝对不可以忽略它。

可以理解Buffer是在内存中开辟的一片区域,用于存放二进制数据。Buffer所开辟的是堆外内存,不是由v8分配的,而是在NodeC++层面实现内存的申请的。

二. 编码的发展

一个字节由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');
}

三. 进制转化

//把任意进制转成十进制
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

四. Buffer的应用

1. 定义buffer的三种方式

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

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];
  }
}

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;
}

封装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;
}

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);

五. 前端二进制对象

前端最常用的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);

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);

createObjectURL来实现

let r = URL.createObjectURL(file);
let img = document.createElement('img');
img.src = r;
document.body.appendChild(img)
URL.revokeObjectURL(r);

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]

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
}

arrayBuffer转化成字符串

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

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)
})

服务端代码

const express = require('express');
const app = express();
app.listen(4444);
app.use(express.static(__dirname));
app.get('/download', (req, res) => {
    res.download('a.pdf');
})
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。