2 min read

Nodejs: 如何逐行讀取檔案,或使用Unix pipe與其他process互動

這篇文章將介紹如何使用Nodejs的readline module來一行一行地讀取檔案, 接著既然都可以從檔案中逐行讀取了,那也可以從standard input中逐行讀取吧, 如此一來,就可以跟其他linux command一樣,一起使用pipe!像下面這樣:

cat words.txt | node wc.js

readline

  • createInterface:
    首先使用readline.createInterface(),需要一個input參數,他需要是一個stream.Readable, 這裡我們使用fs.createReadStream()打開我們的檔案,並作為input,傳給createInterface。

```javascript const readline = require('readline'); const fs = require('fs');

const rl = readline.createInterface({ input: fs.createReadStream('./words.txt'), }); ```

  • Event: "line"
    接著就可以監聽line event,每當從input讀取到換行(\r\n or \r\n),line event就會被發送。 callback function有一個參數,它是個字串。 javascript rl.on('line', (row) => console.log(row));
  • Event: "close"
    當input stream結束的時候,close event就會被發送。 javascript rl.on('close', doSomething);

完整程式碼

最後我們就利用上面的資訊,寫一隻wc.js,來計算檔案中每個字出現的次數,將結果以JSON的格式輸出至stdout上。

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。

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 ,有興趣的可以看看:

其他stream的實例: