Node的数据流模块配合pipe函数可以生成很多有效的文件处理工具,以下代码是一个简单的压缩文件脚本:
const fs = require('fs');
const zlib = require('zlib');
const { Transform } = require('stream');
const file = process.argv[2];
let src = fs.createReadStream(file);
var stats = fs.statSync(file)
let total = 0;
const reportProgress = new Transform({
transform(chunk, encoding, callback) {
total += chunk.length;
let percentage = Math.floor((total / stats['size']) * 100);
if (percentage % 5 == 0) console.log(percentage + '%');
callback(null, chunk);
}
})
src
.pipe(zlib.createGzip())
.pipe(reportProgress)
.pipe(fs.createWriteStream(file + '.gz'))
.on('finish', () => console.log('Done!'));
整个脚本可以被拆分成三个部分去理解:
1. 压缩文件
const fs = require('fs');
const zlib = require('zlib');
const file = process.argv[2];
src
.pipe(zlib.createGzip())
.pipe(fs.createWriteStream(file + '.gz'))
压缩文件逻辑只用六行代码便可实现。Node原生的zlib模块属于duplex数据流,这表示它及可读也可写,所以它可以作为中间的pipe中转站将src的数据写入在内后做压缩处理,然后再被读取。下一步便是通过fs.createWriteStream将文件写出。
2. 自定义Transform Stream
const { Transform } = require('stream');
const reportProgress = new Transform({
transform(chunk, encoding, callback) {
total += chunk.length;
let percentage = Math.floor((total / stats['size']) * 100);
if (percentage % 5 == 0) console.log(percentage + '%');
callback(null, chunk);
}
})
Transform数据流基于Duplex数据流也是双向的,在传入的对象内需要定于名为tranform的函数作为callback。Callback内会传入三个参数,可以对相应的数据流做处理并需要调用第三个参数"callback"去指向下一段数据流直到所有数据都完成处理。
3. 事件监听
.on('finish', () => console.log('Done!'));
所有的数据流都可以通过事件被监听,其中包括结束事件,所以在拼接pipe的同时也添加了on的来监听finish事件。