Buffer(缓冲)

由于Js没有读取和操作二进制数据流的机制,所以nodejs提供了Buffer类来实现这功能,在TPC流或文件I/O中处理字节流,Buffer的实例类似于Js的数组,但对应于V8堆之外的固定大小的原始内存分配。缓冲区的大小是在创建时建立的,不能动态调整大小

由于计算机是二进制来存储的,无论是字符串,数字,文件,音频,视频等等,例如存储一个字符A,可以通过charCodeAt先转为数字(76 => 01001100),然后通过字符集就可以确定对应的数字代表的意义,常见的字符集有Unicode和ASCII等,字符集定义了什么样数字代表一个字符,字符编码则定义了在二进制文件中要用多少个bit来代表这个数字,其他的文件,视频都有相应的规则来定义如何存储响应的二进制数据

Buffer用法

Stream(流)

nodejs的流是用来进行二进制数据的传输,流的实现也是使用buffer来缓冲数据,stream继承了 EventEmitter 接口,可以监听数据的流动状态,达到数据流动的目的,流定义了四种类型

  • Readable - 只读的流,例如 fs.createReadStream()
  • Writable - 只写的流,例如 fs.createWriteStream()
  • Duplex - 可读可写流,例如 net.Socket
  • Transform - 可读可写可修改可转换,例如 zlib.createDeflate()

Stream用法

比如我们使用 fs.createReadStream 来读取一个文件,会把文件数据分块处理,看下面例子,默认创建的流每一块的 buffer 的阈值 highWaterMark 是16kb,但是用 createReadStream 方法创建的是默认是64kb

const fs = require("fs");
fs.stat('./img.jpg', (err, res) => {
    console.log(res.size / 1024 / 1024);   // 6.79m的数据
});

// 使用
const rs = fs.createReadStream("./img.jpg");
const ws = fs.createWriteStream('./copy.jpg');

let i = 0;
rs.on('data', d => {
    let size = d.length / 1024;        // 每次64k,最后一次不满64k
    console.log(++i);                  // 触发109次
    ws.write(d);
});

const ws2 = fs.createWriteStream('./copy2.jpg');
rs.pipe(ws2);

延伸阅读

认识node核心模块--从Buffer、Stream到fs

深入理解 Node.js Stream 内部机制