Node.js で標準入力から同期的に一行読み取る
前座:既存の手法(非同期 or 入力全行)
主に競技プログラミングなどのシーンで標準入力からデータが受け渡されることは多いです。競技でなくとも、同様の形式でコーディングテストが行われることもあります。
こういったときに Node.js だと少し煩雑な手順を取る必要があります。
readline
const rl = require("readline").createInterface({
input: process.stdin,
output: process.stdout,
});
const lines = [];
rl.on("line", (line) => {
lines.push(line);
// ... 多分入力処理
});
rl.on("close", () => {
// 入力が閉じたのでデータは受け取った
// データを全て受け取った前提の処理がここ
});
何も知らない人から見ると呪文です。
上から順に実行されるのはそうなのですが、rl.on
では「イベントに対するコールバックを設定」という処理が行われるだけなので rl.on("line", ...);
の直後に処理を書いたとしてもデータが入っているとは限らないのが罠です。
インタラクティブな場面では気持ちがいいかもしれません。
fs.readFileSync
const fs = require("fs");
const wholeInput = fs.readFileSync("/dev/stdin", "utf8");
const inputLines = wholeInput.split("\n");
const n = Number(inputLines[0]);
// ...
こちらは比較的まともです。標準入力からの入力を全て文字列として受け取るものです。
強いて欠点を挙げるとすれば以下のようになるでしょう。
- インタラクティブな場面には向かない
- 行を取るには
split
してインデックスを指定する必要がある
作ってみた
正直上の二つがあれば特に困らないのですが、例えば ruby や python などで簡単に利用できる gets
や input()
などのような関数が Node.js にもあればなあ、と思い作ってみました。
使う
ローカルにインストールして利用する場合は npm
で直接 github 上のリポジトリを指定してください。
(10/28 追記)npm に publish しました。
https://www.npmjs.com/package/node-gets
$ npm install --save node-gets
GitHub にあるリポジトリを指定してインストールすることもできます(<owner>/<repository>
と書けば GitHub からインストールできるらしい)。
$ npm install --save cwd-k2/node-gets
(10/28 追記終わり)
以下のような書き心地になります。
const gets = require("node-gets").createGets();
const n = Number(gets().trim());
const a = gets().trim().split(" ").map(Number);
// ...
- 行入力末尾の改行文字などは付いたまま
- EOF 的な感じで入力がなくなると
undefined
を返すようになる
問題点
- テストがない
- ベンチマークがない
- 実装上の問題
一行読むたびに内部のバッファでコピーが発生している(リングバッファにすべきなど色々あると思います)-
\n
以外の文字での分割に対応していない
最後に
他に問題点があったり、直してやったぞということがあれば issue や PR をお願いします。
追記
9/23 追記(簡単 gets
風味の fs.readFileSync
)
gets
風味の fs.readFileSync
)競プロで利用する程度なら次の簡単なスニペットを持っておくのもいいかもな、というのが最近の結論です。
const line =
((l, i = 0) => () => l[i++])
(require("fs").readFileSync(0, "utf8").replace(/\n$/, '').split(/\n/));
次のように利用することができるので、gets
や input()
の気持ちにはなれるかも(願望)。
const n = Number(line());
for (let i = 0; i < n; i++) {
const [name, type] = line().split(' ');
console.log({ name, type });
}
Author And Source
この問題について(Node.js で標準入力から同期的に一行読み取る), 我々は、より多くの情報をここで見つけました https://qiita.com/cwd-k2/items/1d8f696161c901775dd4著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .