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事件。