Buffer
什么是Buffer?
Buffer 是Node.js API 的⼀部分 主要用来处理二进制文件流和TCP流的文件缓存区 内存缓冲区
优势:Buffer 使用堆外内存,不占用堆内存
形式上是字节的形式,8位⼀个字节|0000 0001|0010 0011|0100 0101|0110 0111|
// Buffer 类是全局的对象,可以直接使⽤,官⽅推荐显式引⽤
import { Buffer } from 'buffer';
// new Buffer() 建议弃⽤
Buffer.from()
Buffer.from(array)
Buffer.from(arrayBuffer[, byteOffset[, length]])
Buffer.from(buffer)
Buffer.from(object[, offsetOrEncoding[, length]])
Buffer.from(string[, encoding])
Buffer.alloc(size[, fill[, encoding]])
//fill:默认0, encoding默认值: 'utf8'
// 创建⻓度为 10 的以零填充的缓冲区。
const buf1 = Buffer.alloc(10);
// 创建⻓度为 10 的缓冲区,
// 使⽤值为 `1` 的字节填充。
const buf2 = Buffer.alloc(10, 1);
const buf3 = Buffer.allocUnsafe(10);
// allocUnsafe 优劣
fs.readFile(path[, options], callback)
callback <Function>
data <string> | <Buffer>
Buffer 的应用场景
const fs = require('fs');
const path = require('path');
// function to encode file data to base64 encoded string
function base64_encode(file) {
let bitmap = fs.readFileSync(file);
return Buffer.from(bitmap).toString('base64');
}
// function to create file from base64 encoded string
function base64_decode(base64str, file) {
let bitmap = Buffer.from(base64str, 'base64');
fs.writeFileSync(file, bitmap);
console.log('******** File created from base64 encoded string********');
}
let base64str = base64_encode(path.join(__dirname, './play.png'));
console.log(base64str);
base64_decode(base64str, path.join(__dirname, 'copy.png'));
const fs = require('fs');
const path = require('path');
//
const rs = fs.createReadStream(path.join(__dirname, '1.txt'));
let data = '';
rs.on('data', function (chunk) {
data += chunk;
});
rs.on('end', function () {
console.log(data);
});
乱码的产生
const fs = require('fs');
const path = require('path');
// fs.createReadStream 的 options 中 highWaterMark默认是64k
const rs = fs.createReadStream(path.join(__dirname, '1.txt'),{ highWaterMark: 11 });
let data = '';
rs.on('data', function (chunk) {
data += chunk;
});
rs.on('end', function () {
console.log(data);
});
解决⽅式1
// 可读流有⼀个设置编码的⽅法setEncoding():
// 默认情况下没有设置字符编码,流数据返回的是 Buffer 对象。
// 如果设置了字符编码,则流数据返回指定编码的字符串
let rs = fs.createReadStream('test.md', {highWaterMark: 11});
rs.setEncoding('utf8');
解决⽅式2
// 将⼩Buffer 拼接成⼤Buffer 对象
let chunks = [];
let size = 0;
res.on('data', function (chunk) {
chunks.push(chunk);
size += chunk.length;
});
res.on('end', function () {
let buf = Buffer.concat(chunks, size);
let str = iconv.decode(buf, 'utf8');
console.log(str);
});
Stream
什么是Stream
nodejs Stream类型
- Readable - 可读操作。
- Writable - 可写操作。
- Duplex - 可读可写操作.
Transform - 操 作被写⼊数据,然后读出结果。
pipe 管道 在管道中间对流进⾏处理
```javascript // src/pipe.js var fs = require(“fs”); var zlib = require(‘zlib’); // 压缩 input.txt ⽂件为 input.txt.gz fs.createReadStream(‘input.txt’) .pipe(zlib.createGzip()) .pipe(fs.createWriteStream(‘input.txt.gz’));
console.log(“⽂件压缩完成。”);
pipe实现原理
```javascript
Readable.prototype.pipe = function(dest, options) {
const src = this;
src.on('data', ondata);
function ondata(chunk) {
const ret = dest.write(chunk);
if (ret === false) {
...
src.pause();
}
}
...
// 保持链式调⽤
return dest;
};
Events 事件触发器
Node.js 的⼤部分核心API 都是围绕惯用的异步事件驱动架构构建的
常⽤API
emitter.on(eventName, listener)
emitter.once(eventName, listener)
emitter.off(eventName, listener)
emitter.emit(eventName[, ...args])
/*
emitter.addListener(eventName, listener)
emitter.removeListener(eventName, listener)
*/
//简单实现上述⽅法
class MyEventsEmitter{
constructor(){
this.events = {};
}
// 绑定事件
on(event, cbFn){
if(!this.events[event]){
this.events[event] = [];
}
this.events[event].push(cbFn);
return this;
}
// 解绑事件
off(event, cbFn){
if (this._events[type]) {
// 过滤掉该事件
this._events[type] =
this._events[type].filter(fn => {
return fn !== cbFn
});
}
}
// 只响应⼀次
once(event, cbFn){
const onlyonce = (...args)=> {
this.off(event, cbFn);
cbFn.apply(this, args);
}
this.on(event, onlyonce);
return this;
}
// 触发监听事件
emit(event, ...args){
if (this.events[event]) {
this.events[event].forEach(fn => fn.call(this, ...args));
}
}
}