web-dev-qa-db-ja.com

node.js:stdinからreadSync?

Node.jsのstdinから同期的に読み取ることは可能ですか?なぜなら、私はJavaScriptでJavaScriptコンパイラーにブレインファックを書いているからです(ただの楽しみのため)。 Brainfuckは、同期的に実装する必要がある読み取り操作をサポートしています。

私はこれを試しました:

const fs = require('fs');
var c = fs.readSync(0,1,null,'utf-8');
console.log('character: '+c+' ('+c.charCodeAt(0)+')');

しかし、これはこの出力のみを生成します。

fs:189
  var r = binding.read(fd, buffer, offset, length, position);
              ^
Error: EAGAIN, Resource temporarily unavailable
    at Object.readSync (fs:189:19)
    at Object.<anonymous> (/home/.../stdin.js:3:12)
    at Module._compile (module:426:23)
    at Module._loadScriptSync (module:436:8)
    at Module.loadSync (module:306:10)
    at Object.runMain (module:490:22)
    at node.js:254:10
51
panzi

私はこれがいつ現れたのか分かりませんが、これは役に立つ前進です: http://nodejs.org/api/readline.html

var readline = require('readline');

var rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
  terminal: false
});

rl.on('line', function (cmd) {
  console.log('You just typed: '+cmd);
});

これで、stdinから一度に1行ずつ読み取ることができます。幸せな日々。

19
rjp

やってみました:

fs=require('fs');
console.log(fs.readFileSync('/dev/stdin').toString());

ただし、ファイル全体が読み込まれるまで待機し、scanfやcinのように\ nに戻ることはありません。

53
dhruvbird

これを少しいじった後、私は答えを見つけました:

_process.stdin.resume();
var fs = require('fs');
var response = fs.readSync(process.stdin.fd, 100, 0, "utf8");
process.stdin.pause();
_

応答は2つのインデックスを持つ配列になります。最初のインデックスはコンソールに入力されたデータで、2番目のインデックスは改行文字を含むデータの長さです。

console.log(process.stdin)の最初のパラメーターの名前であるfdというラベルが付いたものを含むすべてのプロパティを列挙するfs.readSync()を決定するのは非常に簡単でした

楽しい! :D

27
Marcus Pope

node.js v0.10.4 の時点で機能するMarcus Popeの回答の更新バージョン:

ご注意ください:

  • 一般的に、 nodeの ストリームインターフェース は、まだflux (半意図のしゃれ)にあり、2 - Unstableの時点でnode.js v0.10.4として分類されています。
  • プラットフォームによって動作が少し異なります。 OS X 10.8.3Windows 7を見てきました:主な違いは次のとおりです: synchronously reading interactive stdin input(by line into the terminal line by line )はWindows 7 でのみ動作します。

更新されたコードは次のとおりです。 256バイトのチャンクで標準入力から同期的に読み取り、入力が利用できなくなるまで

var fs = require('fs');
var BUFSIZE=256;
var buf = new Buffer(BUFSIZE);
var bytesRead;

while (true) { // Loop as long as stdin input is available.
    bytesRead = 0;
    try {
        bytesRead = fs.readSync(process.stdin.fd, buf, 0, BUFSIZE);
    } catch (e) {
        if (e.code === 'EAGAIN') { // 'resource temporarily unavailable'
            // Happens on OS X 10.8.3 (not Windows 7!), if there's no
            // stdin input - typically when invoking a script without any
            // input (for interactive stdin input).
            // If you were to just continue, you'd create a tight loop.
            throw 'ERROR: interactive stdin input not supported.';
        } else if (e.code === 'EOF') {
            // Happens on Windows 7, but not OS X 10.8.3:
            // simply signals the end of *piped* stdin input.
            break;          
        }
        throw e; // unexpected exception
    }
    if (bytesRead === 0) {
        // No more stdin input available.
        // OS X 10.8.3: regardless of input method, this is how the end 
        //   of input is signaled.
        // Windows 7: this is how the end of input is signaled for
        //   *interactive* stdin input.
        break;
    }
    // Process the chunk read.
    console.log('Bytes read: %s; content:\n%s', bytesRead, buf.toString(null, 0, bytesRead));
}
21
mklement0

私はあなたが必要なことを達成できるはずのライブラリを見つけました: https://github.com/anseki/readline-sync

14
Nate Ferrero

重要:Node.jsの寄稿者から .fdは文書化されておらず、内部デバッグ目的 。したがって、コードはこれを参照せず、fs.open/openSyncを使用してファイル記述子を手動で開く必要があります。

Node.js 6では、Bufferを使用してコンストラクターを介してnewのインスタンスを作成することは、その安全性が低いため非推奨です。代わりにBuffer.allocを使用する必要があります。

'use strict';

const fs = require('fs');

// small because I'm only reading a few bytes
const BUFFER_LENGTH = 8;

const stdin = fs.openSync('/dev/stdin', 'rs');
const buffer = Buffer.alloc(BUFFER_LENGTH);

fs.readSync(stdin, buffer, 0, BUFFER_LENGTH);
console.log(buffer.toString());
fs.closeSync(stdin);

また、必要な場合にのみファイル記述子を開いたり閉じたりする必要があります。 stdinからの読み取りを希望するたびにこれを行うと、不要なオーバーヘッドが発生します。

5
James Wright

ノード0.10.24/linuxでこの回避策を使用しました。

var fs = require("fs")
var fd = fs.openSync("/dev/stdin", "rs")
fs.readSync(fd, new Buffer(1), 0, 1)
fs.closeSync(fd)

このコードはEnterキーを押すのを待ちます。ユーザーがEnterキーを押す前に入力した場合、行から1文字を読み取ります。他の文字はコンソールバッファーに残り、以降のreadSyncの呼び出しで読み取られます。

3
vadzim

キーボードで同期読み取りを行う小さなC++アドオンモジュールを作成しました( https://npmjs.org/package/kbd )。

3
user3085414

以下に、「async await」を使用した実装を示します。以下のコードでは、入力は標準入力から取得され、データの受信後、標準入力は「process.stdin.pause();」を使用してデータの待機を停止します。

process.stdin.setEncoding('utf8');

// This function reads only one line on console synchronously. After pressing `enter` key the console will stop listening for data.
function readlineSync() {
    return new Promise((resolve, reject) => {
        process.stdin.resume();
        process.stdin.on('data', function (data) {
            process.stdin.pause(); // stops after one line reads
            resolve(data);
        });
    });
}

// entry point
async function main() {
    let inputLine1 = await readlineSync();
    console.log('inputLine1 = ', inputLine1);
    let inputLine2 = await readlineSync();
    console.log('inputLine2 = ', inputLine2);
    console.log('bye');
}

main();
3
anshul
function read_stdinSync() {
    var b = new Buffer(1024)
    var data = ''

    while (true) {
        var n = fs.readSync(process.stdin.fd, b, 0, b.length)
        if (!n) break
        data += b.toString(null, 0, n)
    }
    return data
}
2
exebook

これを書いて module ファイルまたはstdinから一度に1行を読み取ります。モジュールの名前はline-readerで、ES6 *Generator functionを公開して、一度に1行ずつ繰り返します。これは、readme.mdからのサンプルコード(TypeScript)です。

import { LineReader } from "line-reader"

// FromLine and ToLine are optional arguments
const filePathOrStdin = "path-to-file.txt" || process.stdin
const FromLine: number = 1 // default is 0
const ToLine: number = 5 // default is Infinity
const chunkSizeInBytes = 8 * 1024 // default is 64 * 1024

const list: IterableIterator<string> = LineReader(filePathOrStdin, FromLine, ToLine, chunkSizeInBytes)

// Call list.next to iterate over lines in a file
list.next()

// Iterating using a for..of loop
for (const item of list) {
   console.log(item)
}

上記のコードとは別に、 reposrc > testsフォルダーを見ることができます。

注意:-
line-reader モジュールは、すべてのものをメモリに読み込まず、代わりにジェネレーター関数を使用して、行asyncまたはsyncを生成します。

0
Vikas Gautam