nodo.js: readSync desde stdin?
Es posible leer sincrónicamente desde stdin en el nodo.js? Porque estoy escribiendo un compilador de brainfuck para JavaScript en JavaScript (solo por diversión). Brainfuck admite una operación de lectura que debe implementarse de forma sincrónica.
He intentado esto:
const fs = require('fs');
var c = fs.readSync(0,1,null,'utf-8');
console.log('character: '+c+' ('+c.charCodeAt(0)+')');
Pero esto solo produce esta salida:
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
10 answers
No tengo ni idea de cuándo apareció esto, pero este es un paso adelante útil: 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);
});
Ahora puedo leer línea a línea desde stdin. Días felices.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-01-25 01:11:12
¿has probado:
fs=require('fs');
console.log(fs.readFileSync('/dev/stdin').toString());
Sin embargo, esperará a que se lea TODO el archivo, y no volverá en \n como scanf o cin.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-04-26 18:01:36
Después de jugar un poco con esto, encontré la respuesta:
process.stdin.resume();
var fs = require('fs');
var response = fs.readSync(process.stdin.fd, 100, 0, "utf8");
process.stdin.pause();
La respuesta será una matriz con dos índices, el primero serán los datos introducidos en la consola y el segundo será la longitud de los datos incluyendo el carácter de nueva línea.
Fue bastante fácil determinar cuando console.log(process.stdin)
que enumera todas las propiedades, incluyendo una etiqueta fd
que es, por supuesto, el nombre del primer parámetro fs.readSync()
Disfrute! : D
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-16 20:15:33
Una versión actualizada de la respuesta de Marcus Pope que funciona como de nodo.js v0.10.4:
Tenga en cuenta:
- En general, las interfaces de flujo del nodo todavía están en flujo (juego de palabras a medias) y todavía se clasifican como
2 - Unstable
a partir denode.js v0.10.4
. - Diferentes plataformas se comportan ligeramente diferente; He mirado
OS X 10.8.3
yWindows 7
: la principal diferencia es: sincrónicamente leyendo interactivo entrada stdin (escribiendo en la línea terminal por línea) solo funciona en Windows 7.
Aquí está el código actualizado, leyendo sincrónicamente desde stdin en trozos de 256 bytes hasta que no haya más entrada disponible :
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));
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-25 19:13:01
Encontré una biblioteca que debería ser capaz de lograr lo que necesitas: https://github.com/anseki/readline-sync
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-11 21:26:06
Importante: Acabo de ser informado por un nodo.js colaborador que .fd
es indocumentado y sirve como un medio para propósitos de depuración interna . Por lo tanto, el código de uno no debe hacer referencia a esto, y debe abrir manualmente el descriptor de archivo con fs.open/openSync
.
En el nodo.js 6, también vale la pena señalar que crear una instancia de Buffer
a través de su constructor con new
está en desuso, debido a su naturaleza insegura. Uno debe usar Buffer.alloc
en su lugar:
'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);
También, uno debe solo abra y cierre el descriptor de archivo cuando sea necesario; hacer esto cada vez que se desee leer desde stdin resulta en una sobrecarga innecesaria.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-27 14:42:35
Escribí un pequeño módulo adicional de C++ que hace que la lectura sincrónica en el teclado ( https://npmjs.org/package/kbd).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-12-10 04:35:48
Usé esta solución en el nodo 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)
Este código espera para presionar ENTER. Lee un carácter de la línea, si el usuario lo introduce antes de presionar ENTER. Otros caracteres permanecerán en el búfer de la consola y se leerán en llamadas posteriores a readSync.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-11 11:12:49
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
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-06 10:34:24
Escribí este módulo para leer una línea a la vez desde file o stdin. El módulo se nombra como line-reader
que expone un ES6 *Generator function
para iterar sobre una línea a la vez. aquí hay un ejemplo de código (en TypeScript) de 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)
}
Aparte del código anterior, también puede echar un vistazo a la carpeta src > tests
en el repositorio .
Nota:-
el módulo line-reader no lee todas las cosas en la memoria, sino que usa la función generator para generar líneas async o sync.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-08 20:33:44