1028.us

管理ページへ

ログアウト

Streamオブジェクト

参考
Node.js Stream を使いこなす


Streamオブジェクトはデータストリーム(データーの流れ)を扱うオブジェクトである。

ファイルの内容を別のファイルにコピーする場合、以下のようにファイルを全て読み込んでから全て書き込む方法がある。後述するように問題があるが、コードが非常に読みやすいというメリットがある。

// ファイルの読み込み
const text = fs.readFileSync('src.txt', 'utf8')
// ファイルの書き込み
fs.writeFileSync('dest.txt', text)

この方法はファイルを読み込んだり書き込んだりしている間は処理がブロッキングされてしまう。特にウェブアプリの場合、ブロッキングされている間は他のブラウザーからの応答をさばくことができない。

非ブロッキング I/O を使ってこのように書き換える。

// ファイルの読み込み
fs.readFile('src.txt', 'utf8', (err, data) => {
  // イベントハンドラでファイルの書き込み
  fs.writeFile('dest.txt', data)
})

読みにくくなってしまう。しかも、全てのデータを読み込んでから全てのデータを書き込むことには変わりはないので、2GB のテキストファイルの場合、メモリを 2GB 消費する。

そこでストリームを使用する。

const src = fs.createReadStream('src.txt', 'utf8')
const dest = fs.createWriteStream('dest.txt', 'utf8')
src.on('data', chunk => dest.write(chunk))
src.on('end', () => dest.end())

この例ではを一定量だけ読み込んでイベントを発生させている。大きなファイルでも全てを読み込むわけではないのでメモリに非常に優しい。

ただ、多少見にくいのでpipe() を使うと一気に読みやすくなる。

const src = fs.createReadStream('src.txt', 'utf8')
const dest = fs.createWriteStream('dest.txt', 'utf8')
src.pipe(dest)

pipe() メソッドは読み取り可能なストリームと書き込み可能なストリームを関連付けるもので、後はよしなにデータを渡してくれる。

Node.js では、ここで例にあげたファイルだけでなく、いくつかのオブジェクトはこの Stream となっている。process.stdout もそうであり、ファイルの内容を標準出力に出力するのもとても簡単である。

const src = fs.createReadStream('src.txt', 'utf8')
src.pipe(process.stdout)

Stream を使うとデータを流れるように扱えるのが分かる。

List of Category