Ich muss einige große (5-10 GB) Protokolldateien in Javascript / Node.js analysieren (ich verwende Cube).
Die Logline sieht ungefähr so aus:
10:00:43.343423 I'm a friendly log message. There are 5 cats, and 7 dogs. We are in state "SUCCESS".
Wir brauchen jede Zeile zu lesen, einige der Parsing (zB Streifen aus 5
, 7
und SUCCESS
), dann diese Daten in Cube - Pumpe ( https://github.com/square/cube ) ihre JS - Client.
Was ist die kanonische Methode in Node, um eine Datei Zeile für Zeile einzulesen?
Es scheint eine ziemlich häufige Online-Frage zu sein:
- http://www.quora.com/Was-ist-der-bester- Weg-zum-Lesen-einer-Datei-Linie-durch-Linie-in-Knoten-js
- Eine Datei zeilenweise in node.js lesen?
Viele der Antworten scheinen auf eine Reihe von Modulen von Drittanbietern zu verweisen:
- https://github.com/nickewing/line-reader
- https://github.com/jahewson/node-byline
- https://github.com/pkrumins/node-lazy
- https://github.com/Gagle/Node-BufferedReader
Dies scheint jedoch eine ziemlich grundlegende Aufgabe zu sein - sicherlich gibt es innerhalb der stdlib eine einfache Möglichkeit, eine Textdatei zeilenweise einzulesen?
Zweitens muss ich dann jede Zeile verarbeiten (z. B. den Zeitstempel in ein Datumsobjekt konvertieren und nützliche Felder extrahieren).
Was ist der beste Weg, um den Durchsatz zu maximieren? Gibt es eine Möglichkeit, die das Lesen in jeder Zeile oder das Senden an Cube nicht blockiert?
Drittens - ich vermute, dass String-Splits verwendet werden und das JS-Äquivalent von enthält (IndexOf! = -1?) Viel schneller ist als reguläre Ausdrücke? Hat jemand viel Erfahrung mit dem Parsen großer Mengen von Textdaten in Node.js?
Prost, Victor
quelle
Antworten:
Ich suchte nach einer Lösung, um sehr große Dateien (gbs) Zeile für Zeile mithilfe eines Streams zu analysieren. Alle Bibliotheken und Beispiele von Drittanbietern entsprachen nicht meinen Anforderungen, da sie die Dateien nicht zeilenweise (wie 1, 2, 3, 4 ..) verarbeiteten oder die gesamte Datei in den Speicher lasen
Die folgende Lösung kann sehr große Dateien Zeile für Zeile mit Stream & Pipe analysieren. Zum Testen habe ich eine 2,1-GB-Datei mit 17.000.000 Datensätzen verwendet. Die Ram-Nutzung überschritt 60 MB nicht.
Installieren Sie zunächst das Event-Stream- Paket:
Dann:
Bitte lassen Sie mich wissen, wie es geht!
quelle
console.log(lineNr)
nach der letzten Zeile Ihres Codes einfügen, wird die endgültige Zeilenanzahl nicht angezeigt, da die Datei asynchron gelesen wird.s.end();
readline
Modul ist ein Schmerz. Es pausiert nicht und verursachte jedes Mal nach 40-50 Millionen einen Fehler. Einen Tag verschwendet. Vielen Dank für die Antwort. Dieser funktioniert perfektSie können das integrierte
readline
Paket verwenden, siehe Dokumentation hier . Ich benutze Stream , um einen neuen Ausgabestream zu erstellen.Die Verarbeitung großer Dateien dauert einige Zeit. Sagen Sie, ob es funktioniert.
quelle
readline
es möglich, den Lesestream anzuhalten / fortzusetzen, um asynchrone Aktionen im Bereich "Sachen erledigen" auszuführen?readline
gab mir viele Probleme, als ich versuchte, Pause / Lebenslauf. Es pausiert den Stream nicht richtig und verursacht eine Menge Probleme, wenn der Downstream-Prozess langsamer istDie Antwort von @gerard hat mir sehr gut gefallen , was es verdient, hier die richtige Antwort zu sein. Ich habe einige Verbesserungen vorgenommen:
Hier ist der Code:
Im Grunde genommen werden Sie es hier folgendermaßen verwenden:
Ich habe dies mit einer 35-GB-CSV-Datei getestet und es hat bei mir funktioniert. Deshalb habe ich mich entschieden, es auf der Antwort von @gerard aufzubauen. Rückmeldungen sind willkommen.
quelle
pause()
Anruf, nicht wahr?Ich habe https://www.npmjs.com/package/line-by-line verwendet, um mehr als 1 000 000 Zeilen aus einer Textdatei zu lesen. In diesem Fall betrug die belegte RAM-Kapazität etwa 50 bis 60 Megabyte.
quelle
lr.cancel()
Methode tatsächlich beendet . Liest die ersten 1000 Zeilen einer 5Gig-Datei in 1 ms. Genial!!!!Abgesehen davon, dass Sie die große Datei Zeile für Zeile lesen, können Sie sie auch Stück für Stück lesen. Weitere Informationen finden Sie in diesem Artikel
quelle
if(bytesRead = chunkSize)
?Die Node.js-Dokumentation bietet ein sehr elegantes Beispiel für die Verwendung des Readline-Moduls.
Beispiel: Lesen Sie den Dateistream Zeile für Zeile
quelle
Ich hatte noch das gleiche Problem. Nachdem ich einige Module verglichen hatte, die diese Funktion zu haben scheinen, entschied ich mich, es selbst zu tun. Es ist einfacher als ich dachte.
Kern: https://gist.github.com/deemstone/8279565
Es deckt die in einem Abschluss geöffnete Datei ab, die
fetchBlock()
einen Block aus der Datei abruft und das Ende in ein Array aufteilt (behandelt das Segment vom letzten Abruf).Ich habe die Blockgröße für jede Leseoperation auf 1024 eingestellt. Dies kann Fehler haben, aber die Codelogik ist offensichtlich. Probieren Sie es selbst aus.
quelle
Node-Byline verwendet Streams, daher würde ich diesen für Ihre riesigen Dateien bevorzugen.
Für Ihre Datumskonvertierungen würde ich moment.js verwenden .
Um Ihren Durchsatz zu maximieren, können Sie einen Software-Cluster verwenden. Es gibt einige nette Module, die das knoteneigene Cluster-Modul recht gut umschließen. Ich mag Cluster-Master von Isaacs. Sie könnten beispielsweise einen Cluster von x Workern erstellen, die alle eine Datei berechnen.
Verwenden Sie für das Benchmarking von Splits und Regexen die Referenzbenchmark.js . Ich habe es bis jetzt nicht getestet. Benchmark.js ist als Knotenmodul verfügbar
quelle
Basierend auf der Beantwortung dieser Fragen habe ich eine Klasse implementiert, mit der Sie eine Datei Zeile für Zeile synchron lesen können
fs.readSync()
. Sie können diese "Pause" und "Wiederaufnahme" machen, indem Sie einQ
Versprechen verwenden (jQuery
anscheinend ist ein DOM erforderlich, daher kann es nicht ausgeführt werdennodejs
):quelle
quelle
Ich habe ein Knotenmodul erstellt, um große Dateien asynchron Text oder JSON zu lesen. Getestet an großen Dateien.
Speichern Sie die Datei einfach als file-reader.js und verwenden Sie sie wie folgt:
quelle