Eine Textdatei mit Node.js lesen?


124

Ich muss eine Textdatei im Terminal übergeben und dann die Daten daraus lesen. Wie kann ich das tun?

node server.js file.txt

Wie gehe ich den Weg vom Terminal aus, wie lese ich das auf der anderen Seite?


Wenn Sie weitere Optionen in der Befehlszeile hinzufügen, können Sie Optimist verwenden .
Jess

stackoverflow.com/questions/6156501/… zeigt eine andere Möglichkeit, eine Textdatei zu lesen
Marc Durdin

Antworten:


172

Sie möchten das process.argvArray verwenden, um auf die Befehlszeilenargumente zuzugreifen, um den Dateinamen und das FileSystem-Modul (fs) zum Lesen der Datei abzurufen . Beispielsweise:

// Make sure we got a filename on the command line.
if (process.argv.length < 3) {
  console.log('Usage: node ' + process.argv[1] + ' FILENAME');
  process.exit(1);
}
// Read the file and print its contents.
var fs = require('fs')
  , filename = process.argv[2];
fs.readFile(filename, 'utf8', function(err, data) {
  if (err) throw err;
  console.log('OK: ' + filename);
  console.log(data)
});

Um dies ein wenig aufzuschlüsseln, process.argvhaben Sie normalerweise die Länge zwei, wobei das nullte Element der "Knoten" -Interpreter und das erste das Skript ist, das der Knoten gerade ausführt. Danach wurden Elemente in der Befehlszeile übergeben. Sobald Sie einen Dateinamen aus argv gezogen haben, können Sie die Dateisystemfunktionen verwenden, um die Datei zu lesen und mit dem Inhalt zu tun, was Sie wollen. Die Beispielnutzung würde folgendermaßen aussehen:

$ node ./cat.js file.txt
OK: file.txt
This is file.txt!

[Bearbeiten] Wie @wtfcoder erwähnt, ist die Verwendung der fs.readFile()Methode " " möglicherweise nicht die beste Idee, da der gesamte Inhalt der Datei gepuffert wird, bevor sie an die Rückruffunktion übergeben wird. Diese Pufferung könnte möglicherweise viel Speicher beanspruchen, nutzt jedoch vor allem nicht eine der Kernfunktionen von node.js - asynchrone E / A mit Ereignissen.

Die "Knoten" -Methode zum Verarbeiten einer großen Datei (oder einer beliebigen Datei) besteht darin, fs.read()jeden verfügbaren Block zu verwenden und zu verarbeiten, wie er vom Betriebssystem verfügbar ist. Um die Datei als solche zu lesen, müssen Sie jedoch Ihre eigene (möglicherweise) inkrementelle Analyse / Verarbeitung der Datei durchführen, und ein gewisses Maß an Pufferung kann unvermeidlich sein.


Super, vielen Dank, sehr hilfreich. Wie könnte ich diese Daten nach Zeilen aufteilen?
Lust auf den

10
@fancy: versuchen Sie es var lines = data.split(/\r?\n/);, dann hat das Array "Zeilen" jede Zeile.
Maerics

1
Dies ist keine gute Idee, wenn die Textdatei groß ist, da alles in den Speicher eingelesen wird. Wenn Sie beispielsweise eine 1000-MB-CSV-Datei unter fs.createFilestream verarbeiten, müssen Sie sich jedoch um die Zeilenaufteilung kümmern, da die Datenblöcke wird (in den meisten Fällen) nicht an die
Liniengrenzen fallen

1
@wtfcoder: ja, sehr guter Punkt. Meine Absicht war es nur, den einfachen Fall des Lesens einer in der Befehlszeile genannten Datei zu demonstrieren. Es gibt offensichtlich viele Feinheiten (insbesondere Leistung), die den Rahmen dieser Frage sprengen.
Maerics

Ich habe eine Lösung für eine ähnliche Frage zum Parsen einer sehr großen Datei mithilfe eines synchronen Streams veröffentlicht. siehe: stackoverflow.com/questions/16010915/…
Gerard

35

Verwenden Sie fs mit dem Knoten.

var fs = require('fs');

try {  
    var data = fs.readFileSync('file.txt', 'utf8');
    console.log(data.toString());    
} catch(e) {
    console.log('Error:', e.stack);
}

Beachten Sie, dass dies die synchrone Version ist.
Rich Werden

@RichWerden was meinst du in diesem Zusammenhang mit "synchron"?
Json

1
Wenn in Node etwas "synchron" ist, stoppt / blockiert es das System, etwas anderes zu tun. Angenommen, Sie haben einen Knoten-Webserver. Wenn während des oben genannten Vorgangs andere Anforderungen eingehen, kann / kann der Server nicht antworten, da er gerade mit dem Lesen der Datei beschäftigt ist.
Rich Werden

27

IMHO, fs.readFile()sollte vermieden werden, da es die gesamte Datei im Speicher lädt und den Rückruf erst aufruft, wenn die gesamte Datei gelesen wurde.

Der einfachste Weg, eine Textdatei zu lesen, besteht darin, sie Zeile für Zeile zu lesen. Ich empfehle einen BufferedReader :

new BufferedReader ("file", { encoding: "utf8" })
    .on ("error", function (error){
        console.log ("error: " + error);
    })
    .on ("line", function (line){
        console.log ("line: " + line);
    })
    .on ("end", function (){
        console.log ("EOF");
    })
    .read ();

Für komplexe Datenstrukturen wie .properties oder JSON-Dateien müssen Sie einen Parser verwenden (intern sollte auch ein gepufferter Reader verwendet werden).


7
Vielen Dank, dass Sie auf diese Technik hingewiesen haben. Sie haben Recht, dass dies der beste Weg ist, aber ich dachte nur, dass es im Zusammenhang mit dieser Frage, die meiner Meinung nach einen anspruchslosen Anwendungsfall betrifft, etwas verwirrend ist. Wie oben erwähnt, gibt es keinen Grund, fs.readFile()oder nicht zu verwenden, wenn es sich nur um eine kleine Datei handelt, die an ein Befehlszeilentool übergeben wird fs.readFileSync(). Es muss eine riesige Datei sein, um ein merkliches Warten zu verursachen. Eine JSON-Konfigurationsdatei wie package.json ist wahrscheinlich unter 1 KB groß, also können Sie es einfach fs.readFile()und JSON.parse()so.
John Starr Dewar

1
BufferedReader hat möglicherweise seine Signatur geändert. Ich musste BufferedReader durch BufferedReader, DataReader, ersetzen, wobei BufferedReader das Modul war. Siehe github.com/Gagle/Node-BufferedReader
bnieland

13
Ich sehe, dass BufferedReader jetzt veraltet ist.
Marc Rochkind

6

Sie können readstream und pipe verwenden, um die Datei Zeile für Zeile zu lesen, ohne die gesamte Datei einmal in den Speicher einzulesen.

var fs = require('fs'),
    es = require('event-stream'),
    os = require('os');

var s = fs.createReadStream(path)
    .pipe(es.split())
    .pipe(es.mapSync(function(line) {
        //pause the readstream
        s.pause();
        console.log("line:", line);
        s.resume();
    })
    .on('error', function(err) {
        console.log('Error:', err);
    })
    .on('end', function() {
        console.log('Finish reading.');
    })
);

5

Ich poste ein vollständiges Beispiel, an dem ich endlich gearbeitet habe. Hier lese ich in einer Datei rooms/rooms.txtaus einem Skriptrooms/rooms.js

var fs = require('fs');
var path = require('path');
var readStream = fs.createReadStream(path.join(__dirname, '../rooms') + '/rooms.txt', 'utf8');
let data = ''
readStream.on('data', function(chunk) {
    data += chunk;
}).on('end', function() {
    console.log(data);
});
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.