ファイルを読み込んで、行番号をくっつけてファイルに出力するプログラム。想像以上にややこしかったのでメモ。Node 9.7.1で動作確認。
const fs = require('fs')
const readline = require('readline')
const createLineWriter = stream => {
let count = 0
return line => {
++count
stream.write(`${count} ${line}\n`)
}
}
const input = fs.createReadStream('test.txt','utf8')
const rl = readline.createInterface({ input })
const out = fs.createWriteStream('testOutput.txt')
const writer = createLineWriter(out)
rl.on('line',line=>{
writer(line)
})
rl.on('close',()=>{
out.close()
})
ファイルサイズが大きいことを想定すると、Streamで処理したい。Streamから行ごとにデータを切り出すのはreadlineモジュールがやってくれる。lineイベントが来たら対応する関数が呼ばれるが、行番号を覚えておくなどの処理が必要なのでクロージャにした。
readline.createInterface()
はinputだけでなくoutputのStreamを設定できる。これを利用して、readline.writeを使って実装できないか、とも考えたが、どうもうまくいかないらしいということが、StackOverflowでの議論があったのでこの実装にしたことを付記しておく。この議論では、outputをTTYであるかのように偽装すればうまくいくとのことであったが、そこまでTrickyなことをしたくない。
補足:文字列を行ごとに区切るのは以下のスニペットでうまくいく。Streamとかめんどい場合はこっちも検討
> 'hello\nworld\n123'.split(/(?:\r\n|\r|\n)/g)
[ 'hello', 'world', '123' ]