node.js: readSync из стандартного ввода? - PullRequest
50 голосов
/ 07 августа 2010

Можно ли синхронно читать из stdin в node.js? Потому что я пишу брейкфук для компилятора 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

Ответы [ 11 ]

50 голосов
/ 26 апреля 2011

Вы пробовали:

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

Тем не менее, он будет ожидать, когда будет прочитан ВЕСЬ файл, и не вернется к \ n, как scanf или cin.

27 голосов
/ 17 февраля 2012

Немного поигравшись с этим, я нашел ответ:

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

Ответом будет массив с двумя индексами, первый из которых будет данными, введенными в консоль, а второй - длиной данных, включая символ новой строки.

Было довольно легко определить, когда вы console.log(process.stdin), который перечисляет все свойства, включая одно, помеченное fd, которое, конечно, является именем первого параметра для fs.readSync()

Наслаждайтесь! : D

21 голосов
/ 17 апреля 2013

Обновленная версия ответа Маркуса Поупа о том, что работает с node.js v0.10.4 :

Обратите внимание:

  • В общем, потоковые интерфейсы узла все еще находятся в движении (каламбур наполовину предназначен) и по-прежнему классифицируются как 2 - Unstable с node.js v0.10.4.
  • Различные платформы ведут себя немного по-разному;Я смотрел на OS X 10.8.3 и Windows 7: главное отличие: синхронно чтение интерактивный ввод stdin (вводя строку в строку за строкой) работает тольков 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));
}
19 голосов
/ 25 января 2013

Я не знаю, когда это появилось, но это полезный шаг вперед: 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);
});

Теперь я могу читать по очереди из стандартного ввода. Счастливые дни.

13 голосов
/ 12 мая 2015

Я нашел библиотеку, которая должна быть в состоянии выполнить то, что вам нужно: https://github.com/anseki/readline-sync

5 голосов
/ 27 июня 2016

Важное замечание: Я только что сообщил участнику 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);

Также следует открывать и закрывать файловый дескриптор только при необходимости;Делая это каждый раз, когда вы хотите прочитать из стандартного ввода, приводит к ненужным накладным расходам.

4 голосов
/ 11 октября 2018
process.stdin.setEncoding('utf8');
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);
        });
    });
}

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

main();
3 голосов
/ 15 января 2014

Я использовал этот обходной путь на узле 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.Другие символы останутся в буфере консоли и будут прочитаны при последующих вызовах readSync.

3 голосов
/ 10 декабря 2013

Я написал небольшой дополнительный модуль C ++, который выполняет синхронное чтение на клавиатуре (https://npmjs.org/package/kbd).

2 голосов
/ 06 июля 2016
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
}
...