73 Stimmen

node.js: readSync von stdin?

Ist es möglich, synchron von stdin in node.js zu lesen? Weil ich schreibe ein Brainfuck zu JavaScript-Compiler in JavaScript (nur zum Spaß). Brainfuck unterstützt eine Leseoperation, die synchron implementiert werden muss.

Ich habe dies versucht:

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

Dies führt jedoch nur zu dieser Ausgabe:

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

0 Stimmen

Sparen Sie sich Zeit und verwenden Sie eine gut gepflegte npm-Bibliothek, die das Lesen von stdin abstrahiert, npmjs.com/package/get-stdin .

8voto

anshul Punkte 117

Hier ist die Implementierung mit "async await". Im folgenden Code wird die Eingabe von der Standardeingabe genommen und nach dem Empfang der Daten wird die Standardeingabe angehalten, um auf Daten zu warten, indem `process.stdin.pause();` verwendet wird.

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();

2 Stimmen

Bitte erläutern Sie, wie und warum Ihr Code funktioniert, um Menschen zu helfen, die in Zukunft vor ähnlichen Problemen stehen

1 Stimmen

Vielen Dank, das ist genau das, was ich brauchte. Bestätigt, in Node 10 zu arbeiten

0 Stimmen

Das hat auch mir geholfen. Es ist eine gute Antwort, aber Sie sollten erklären, was und warum Sie tun, damit es jeder verstehen kann.

7voto

James Wright Punkte 3001

Wichtig: Ich wurde gerade von einem Node.js-Mitarbeiter informiert, dass .fd ist undokumentiert und dient als Mittel zur internen Fehlersuche . Daher sollte der eigene Code nicht darauf verweisen, sondern den Dateideskriptor manuell öffnen mit fs.open/openSync .

In Node.js 6 ist es außerdem erwähnenswert, dass das Erstellen einer Instanz von Buffer über seinen Konstruktor mit new ist aufgrund seiner unsicheren Natur veraltet. Man sollte verwenden Buffer.alloc stattdessen:

'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);

Außerdem sollte man den Dateideskriptor nur dann öffnen und schließen, wenn es notwendig ist; dies jedes Mal zu tun, wenn man von stdin lesen möchte, führt zu unnötigem Overhead.

2 Stimmen

重要です。 .fd ist derzeit dokumentiert .

7voto

user3479450 Punkte 121

Der folgende Code liest sync von stdin. Die Eingabe wird bis zu einem Zeilenumbruch / einer Eingabetaste gelesen. Die Funktion gibt eine Zeichenkette der Eingabe mit Zeilenvorschüben ( \n ) und Zeilenumbrüche ( \r ) verworfen. T

function prompt(){
    var fs = require("fs");

    var rtnval = "";

    var buffer = Buffer.alloc ? Buffer.alloc(1) : new Buffer(1);

    for(;;){
        fs.readSync(0, buffer, 0, 1);   //0 is fd for stdin
        if(buffer[0] === 10){   //LF \n   return on line feed
            break;
        }else if(buffer[0] !== 13){     //CR \r   skip carriage return
            rtnval += new String(buffer);
        }
    }

    return rtnval;
}

0 Stimmen

En fs.readSync Aufruf wird nach EOF geworfen, also achten Sie darauf, ihn in ein try/catch zu verpacken.

6voto

exebook Punkte 29372
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 Stimmen

Das war ein Schatz. Danke fürs Teilen. Ich werde es in mein Open-Source-Node-Modul implementieren. Werde zurückkommen, um den Link zum Node-Modul nach einigen Tests zu teilen. Danke!

0 Stimmen

Hier ist das neue Modul, das auf Ihrer Idee basiert:- Zeilenleser

0 Stimmen

@VikasGautam Danke, gut gemacht. Lesen Sie die gesamte stdin auf einmal oder geben Sie die Zeilen so aus, wie sie kommen?

3voto

vadzim Punkte 441

Ich habe diesen Workaround auf Node 0.10.24/Linux verwendet:

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

Dieser Code wartet auf das Drücken von ENTER. Er liest ein Zeichen aus der Zeile, wenn der Benutzer es vor dem Drücken von ENTER eingibt. Die anderen Zeichen bleiben im Konsolenpuffer und werden bei nachfolgenden Aufrufen von readSync gelesen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X