25

RingoJS には、最後に到達するまでストリーム全体を読み取ることができる関数が呼び出されます。readこれは、コマンド ライン アプリケーションを作成する場合に便利です。たとえば、次のようなtac プログラムを作成できます。

#!/usr/bin/env ringo

var string = system.stdin.read(); // read the entire input stream
var lines = string.split("\n");   // split the lines

lines.reverse();                  // reverse the lines

var reversed = lines.join("\n");  // join the reversed lines
system.stdout.write(reversed);    // write the reversed lines

これにより、シェルを起動してtacコマンドを実行できます。次に、必要な数の行を入力し、完了したらCtrl+ D(またはWindows では +) を押して、送信のCtrl終了知らせることができます。Z

node.jsで同じことをしたいのですが、そうする関数が見つかりません。readSync ライブラリの関数を使用しfsて次のようにシミュレートすることを考えましたが、役に立ちませんでした。

fs.readSync(0, buffer, 0, buffer.length, null);

stdin (最初の引数)のファイル記述子0は. したがって、キーボードからデータを読み取る必要があります。代わりに、次のエラーが表示されます。

Error: ESPIPE, invalid seek
    at Object.fs.readSync (fs.js:381:19)
    at repl:1:4
    at REPLServer.self.eval (repl.js:109:21)
    at rli.on.self.bufferedCmd (repl.js:258:20)
    at REPLServer.self.eval (repl.js:116:5)
    at Interface.<anonymous> (repl.js:248:12)
    at Interface.EventEmitter.emit (events.js:96:17)
    at Interface._onLine (readline.js:200:10)
    at Interface._line (readline.js:518:8)
    at Interface._ttyWrite (readline.js:736:14)

入力テキスト ストリーム内のすべてのデータを同期的に収集し、それを node.js 内の文字列として返すにはどうすればよいでしょうか? コード例は非常に役立ちます。

4

6 に答える 6

32

node.js はイベントおよびストリーム指向であるため、stdin およびバッファ結果の終了まで待機する API はありませんが、手動で行うのは簡単です

var content = '';
process.stdin.resume();
process.stdin.on('data', function(buf) { content += buf.toString(); });
process.stdin.on('end', function() {
    // your code here
    console.log(content.split('').reverse().join(''));
});

ほとんどの場合、データをバッファリングせず、到着したチャンクを処理しない方がよいでしょう (xml や zlib などの既に利用可能なストリーム パーサーのチェーン、または独自の FSM パーサーを使用します)。

于 2012-11-16T05:53:57.753 に答える
15

重要なのは、次の 2 つの Stream イベントを使用することです。

Event: 'data'
Event: 'end'

stream.on('data', ...)データ データをバッファ (バイナリの場合) または文字列に収集する必要があります。

on('end', ...)完了したバッファでコールバックを呼び出す必要があるため、またはそれをインライン化して Promises ライブラリを使用して return を使用できる場合。

于 2012-11-16T05:25:46.520 に答える
5

concat-streamと呼ばれる、その特定のタスク用のモジュールがあります。

于 2014-05-05T18:46:09.300 に答える
0

Windows では、ここに投稿された他のソリューションでいくつか問題がありました。入力がない場合、プログラムは無期限に実行されます。

これは、非同期ジェネレーターを使用した最新の NodeJS の TypeScript 実装でありfor await、古いコールバック ベースの API を使用するよりもかなり単純で堅牢であり、これは Windows で機能しました。

import process from "process";

/**
 * Read everything from standard input and return a string.
 * 
 * (If there is no data available, the Promise is rejected.)
 */
export async function readInput(): Promise<string> {  
  const { stdin } = process;

  const chunks: Uint8Array[] = [];

  if (stdin.isTTY) {
    throw new Error("No input available");
  }

  for await (const chunk of stdin) {
    chunks.push(chunk);
  }

  return Buffer.concat(chunks).toString('utf8');
}

例:

(async () => {
  const input = await readInput();

  console.log(input);
})();

try/catch( Promise の拒否を処理し、入力がない場合によりわかりやすいエラー メッセージを表示する場合は、を追加することを検討してください。)

于 2021-09-15T12:54:13.170 に答える