Buffer

JavaScript 语言自身只有字符串数据类型,没有二进制数据类型。

但在处理像TCP流或文件流时,必须使用到二进制数据。因此在 Node.js中,定义了一个 Buffer 类,该类用来创建一个专门存放二进制数据的缓存区。

在 Node.js 中,Buffer 类是随 Node 内核一起发布的核心库。Buffer 库为 Node.js 带来了一种存储原始数据的方法,可以让 Node.js 处理二进制数据,每当需要在 Node.js 中处理I/O操作中移动的数据时,就有可能使用 Buffer 库。原始数据存储在 Buffer 类的实例中。一个 Buffer 类似于一个整数数组,但它对应于 V8 堆内存之外的一块原始内存。

buffer中存储的是16进制,将node的2进制保存为16进制存储

字节:
utf8(3个字节)
gbk/gb2312(2个字节)

buffer基本使用

const buffer = Buffer.from("哈哈"); // 创建 buffer 对象
console.log(buffer); // 可以看出打印出6个字节
buffer.toString(); // 转换成string
console.log(buffer.toString('base64')); // buffer转换成base64

创建buffer对象

const buf1 = Buffer.alloc(10); // 定义字节长度为10的buffer
const buf2 = Buffer.from([1, 2, 3]); 创建一个包含 [0x1, 0x2, 0x3] 的 Buffer。
const buf3 = Buffer.from("Buffer创建方法"); // 根据字符串创建buffer

Buffer 中常见的方法

数组的方法, forEach, slice, 等等

buf3.forEach(b => {
    console.log(b);
})
const b1 = Buffer.from("你");
const b2 = Buffer.from("好");
const big = Buffer.alloc(6);
b1.copy(big, 0, 0 ,3);
b2.copy(big, 3, 0, 3);
const big = Buffer.concat([b1, b2]);
const fs = require('fs');
fs.readFile('./a.txt', (err, data) => {
    console.log(data); // <Buffer e5 93 88>
})
const fs = require('fs');
const path = require('path');
const rs = fs.createReadSteam(path.resolve(__dirname, 'name.txt'), {
    flags: 'r', // r w 读和写权限
    highWaterMark: 4, // 每次预计读取多少个
    encoding: null,
    autoClose: true, // 读取完毕,关闭文件
    start: 0,
    end: 5 // slice(start, end) 包含end的
})
// 流 默认流是暂停模式,非流动模式,内部会监控你有没有监听data事件 rs.emit('data', 123);
const arr = [];
rs.on('data', function(chunk) {
    arr.push(chunk);
    rs.pause(); // 暂停data事件的触发  rs.play(); 继续
});
rs.on('end', function() {
    console.log(Buffer.concat(arr).toString()); // 读取完毕
});

rs.on('error', function(error) {
    console.log(error);
})

文件压缩zlib

基于zlib库和buffer进行文件压缩

const zlib = require('zlib');
const fs = require('fs');
const rs = fs.cerateReadStream('jquery.js');
const ws = fs.cerateWriteStream('jquery.js.gz');
const gz = zlib,createGzip();
rs.pipe(gz).pipe(ws);
ws.on('error', (err) => {
    console.log('失败');
})
ws.on('finish', () => {
    console.log('完成')
})

服务器压缩文件

const http = require('http'); // 服务模块
const fs = require('fs'); // 读取文件
const zlib = require('zlib'); // 压缩模块

const server = http.cerateServer((req, res) => {
    const rs = fs.cerateReadStream(`www${req.url}`);
    res.setHeader('content-encoding', 'gzip'); // 设置响应头
    const gz = zlib.createGzip(); // gz压缩
    rs.pipe(gz).pipe(res); // 压缩后返回给前端
    rs.on('error', err => { // 监听失败
        res.setHeader(404);
        res.write('Not Found');
        res.end();
       console.log('读取失败')
    })
    rs.on('finish', err => { // 传输完成
       console.log('写入完成')
    })
}).listen(8080);

服务端压缩成gzip需要设置响应头,content-encoding: gzip, 否则无法加载。

面向字节的设备: 一个一个字节输入, 比如键盘

面向流的设备: 网卡,一块数据