Node.js: readSync из stdin?
Можно ли синхронно читать из 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
Ответы
Ответ 1
Я не знаю, когда это появилось, но это полезный шаг вперед: 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. Счастливые дни.
Ответ 2
Вы пробовали:
fs=require('fs');
console.log(fs.readFileSync('/dev/stdin').toString());
Однако он будет ожидать чтения ENTIRE файла и не будет возвращаться на \n, например scanf или cin.
Ответ 3
После того, как я немного поиграл с этим, я нашел ответ:
process.stdin.resume();
var fs = require('fs');
var response = fs.readSync(process.stdin.fd, 100, 0, "utf8");
process.stdin.pause();
response будет массивом с двумя индексами, первым из которых являются данные, введенные в консоль, а вторая будет длиной данных, включая символ новой строки.
Было довольно легко определить, когда вы console.log(process.stdin)
перечисляете все свойства, включая один помеченный fd
, который, конечно же, является именем первого параметра для fs.readSync()
Наслаждайтесь!
: D
Ответ 4
Обновленная версия Marcus Pope отвечает, что работает как node.js v0.10.4:
Обратите внимание:
- В общем, node потоковые интерфейсы все еще находятся в движении (наполовину предназначены для ползунков) и являются все еще классифицируется как
2 - Unstable
как node.js v0.10.4
.
- Различные платформы ведут себя несколько иначе; Я посмотрел на
OS X 10.8.3
и Windows 7
: главное отличие: синхронно чтение интерактивного ввода stdin (путем ввода строки по строке) работает только в Windows 7.
Здесь обновленный код , который синхронно считывает из stdin в 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 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));
}
Ответ 5
Я нашел библиотеку, которая должна быть в состоянии выполнить то, что вам нужно: https://github.com/anseki/readline-sync
Ответ 6
Я написал небольшой дополнительный модуль С++, который делает синхронное чтение на клавиатуре (https://npmjs.org/package/kbd).
Ответ 7
Важно: Я только что сообщил вкладчику 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, вы получаете ненужные накладные расходы.
Ответ 8
Я использовал это обходное решение для node 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.
Ответ 9
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
}
Ответ 10
Я написал этот модуль для чтения одной строки за раз из файла или stdin. Модуль называется line-reader
, который предоставляет ES6 *Generator function
итерацию по одной строке за раз. вот пример кода (в TypeScript) из readme.md.
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)
}
Помимо вышеприведенного кода вы также можете посмотреть папку src > tests
в repo.
Примечание: - Страница
line-reader модуль не считывает все данные в память, а использует генераторную функцию для генерации строк async или sync.