這篇文章將介紹如何使用Nodejs的readline module來一行一行地讀取檔案, 接著既然都可以從檔案中逐行讀取了,那也可以從standard input中逐行讀取吧, 如此一來,就可以跟其他linux command一樣,一起使用pipe!像下面這樣:
1
cat words.txt | node wc.js
readline
createInterface:
首先使用readline.createInterface(),需要一個input參數,他需要是一個stream.Readable, 這裡我們使用fs.createReadStream()打開我們的檔案,並作為input,傳給createInterface。1 2 3 4 5 6
const readline = require('readline'); const fs = require('fs'); const rl = readline.createInterface({ input: fs.createReadStream('./words.txt'), });
- Event: “line”
接著就可以監聽lineevent,每當從input讀取到換行(\r、\nor\r\n),line event就會被發送。 callback function有一個參數,它是個字串。1
rl.on('line', (row) => console.log(row));
- Event: “close”
當input stream結束的時候,closeevent就會被發送。1
rl.on('close', doSomething);
完整程式碼
最後我們就利用上面的資訊,寫一隻wc.js,來計算檔案中每個字出現的次數,將結果以JSON的格式輸出至stdout上。
1
2
3
4
5
6
7
8
9
10
11
12
const readline = require('readline');
const fs = require('fs');
const input = fs.createReadStream('./words.txt');
const rl = readline.createInterface({ input });
const count = {}
rl.on('line', row => {
count[row] = (count[row] || 0) + 1
})
rl.on('close', () => console.log(JSON.stringify(count)))
unix pipe
這邊示範如何從stdin中讀取資料流,就可以使用shell pipe ( | ),讀取來自前一個程式的output了。
只需將readline.createInterface的input參數,從fs.createReadStream('./words.txt')改成 process.stdin就行了!因為他們都是stream.Readable的implementation。
1
2
3
4
5
6
7
8
9
10
11
12
const readline = require('readline');
//只改了這行
const input = process.stdin;
const rl = readline.createInterface({ input });
const count = {}
rl.on('line', row => {
count[row] = (count[row] || 0) + 1
})
rl.on('close', () => console.log(JSON.stringify(count)))
summary
感謝你的閱讀~ 這篇文章示範了如何使用readline模組來逐行讀取檔案, 並且看到了兩個stream.Readable的實例,體會到了stream的好用之處。
另外我還有寫過另一篇一樣功能,只不過是用golang寫的,stream.Readable可以類比為golang中的io.Reader ,有興趣的可以看看:
[Golang] 如何逐行讀取檔案,或使用shell pipe到go process
其他stream的實例:
How to stream data from Blob Storage at your HTTP server using Azure and express.js
Comments powered by Disqus.