Ich versuche, eine große Datei zeilenweise zu lesen. Ich habe eine Frage zu Quora gefunden , die sich mit dem Thema befasst, aber mir fehlen einige Verbindungen, um das Ganze zusammenzufügen.
var Lazy=require("lazy");
new Lazy(process.stdin)
.lines
.forEach(
function(line) {
console.log(line.toString());
}
);
process.stdin.resume();
Das Bit, das ich herausfinden möchte, ist, wie ich eine Zeile nach der anderen aus einer Datei anstelle von STDIN wie in diesem Beispiel lesen kann.
Ich habe es versucht:
fs.open('./VeryBigFile.csv', 'r', '0666', Process);
function Process(err, fd) {
if (err) throw err;
// DO lazy read
}
aber es funktioniert nicht. Ich weiß, dass ich zur Not auf etwas wie PHP zurückgreifen könnte, aber ich würde das gerne herausfinden.
Ich glaube nicht, dass die andere Antwort funktionieren würde, da die Datei viel größer ist als der Server, auf dem ich sie ausführe, über Speicher verfügt.
javascript
node.js
file-io
lazy-evaluation
Alex C.
quelle
quelle
fs.readSync()
. Sie können binäre Oktette in einen Puffer lesen, aber es gibt keine einfache Möglichkeit, mit partiellen UTF-8- oder UTF-16-Zeichen umzugehen, ohne den Puffer zu überprüfen, bevor Sie ihn in JavaScript-Zeichenfolgen übersetzen und nach EOLs suchen. DerBuffer()
Typ verfügt nicht über so viele Funktionen, die auf seinen Instanzen ausgeführt werden können wie native Zeichenfolgen, aber native Zeichenfolgen können keine Binärdaten enthalten. Es scheint mir, dass das Fehlen einer integrierten Methode zum Lesen von Textzeilen aus beliebigen Dateihandles eine echte Lücke in node.js darstellt.if (line.length==1 && line[0] == 48) special(line);
node
den API-Dokumenten github.com/nodejs/node/pull/4609Antworten:
Seit Node.js v0.12 und ab Node.js v4.0.0 gibt es ein stabiles Readline- Kernmodul. Hier ist der einfachste Weg, Zeilen aus einer Datei ohne externe Module zu lesen:
Oder alternativ:
Die letzte Zeile wird korrekt gelesen (ab Node v0.12 oder höher), auch wenn kein Finale vorhanden ist
\n
.UPDATE : Dieses Beispiel wurde der offiziellen API-Dokumentation von Node hinzugefügt .
quelle
rl.on('close', cb)
Für eine so einfache Operation sollte keine Abhängigkeit von Modulen von Drittanbietern bestehen. Geh einfach.
quelle
line
Ereignisse treten erst nach dem Treffer auf\n
, dh alle Alternativen werden übersehen (siehe unicode.org/reports/tr18/#Line_Boundaries ). # 2, Daten nach dem letzten\n
werden stillschweigend ignoriert (siehe stackoverflow.com/questions/18450197/… ). Ich würde diese Lösung als gefährlich bezeichnen, da sie für 99% aller Dateien und für 99% der Daten funktioniert, für den Rest jedoch stillschweigend fehlschlägt . Wann immer Sie dies tun, habenfs.writeFileSync( path, lines.join('\n'))
Sie eine Datei geschrieben, die von der obigen Lösung nur teilweise gelesen wird.readline
Paket verhält sich für einen erfahrenen Unix / Linux-Programmierer wirklich bizarr.rd.on("close", ..);
kann als Rückruf verwendet werden (tritt auf, wenn alle Zeilen gelesen werden)Sie müssen nicht
open
die Datei, sondern müssen eine erstellenReadStream
.fs.createReadStream
Übergeben Sie dann diesen Stream an
Lazy
quelle
new lazy(fs.createReadStream('...')).lines.forEach(function(l) { /* ... */ }).join(function() { /* Done */ })
new lazy(...).lines.forEach(...).on('end', function() {...})
.on('end'...
nach.forEach(...)
, wenn in der Tat verhielten sich alles wie erwartet funktioniert, wenn ich das Ereignis gebunden zuerst .Es gibt ein sehr schönes Modul zum zeilenweisen Lesen einer Datei, es heißt Zeilenleser
damit schreibst du einfach:
Sie können die Datei sogar mit einer Schnittstelle im Java-Stil iterieren, wenn Sie mehr Kontrolle benötigen:
quelle
process/stdin
). Zumindest wenn es möglich ist, ist es sicherlich nicht offensichtlich, wenn man den Code liest und versucht.readline
Kernmoduls zu lesen .function(reader)
undfunction(line)
sollte sein:function(err,reader)
undfunction(err,line)
.line-reader
Liest die Datei nur für den Datensatz asynchron. Die synchrone Alternative dazu istline-reader-sync
quelle
Update im Jahr 2019
Ein großartiges Beispiel ist bereits in der offiziellen Nodejs-Dokumentation veröffentlicht. Hier
Dies setzt voraus, dass die neuesten Nodejs auf Ihrem Computer installiert sind. > 11.4
quelle
await
zwischen demcreateInterface()
Aufruf und dem Start derfor await
Schleife ein s liegt , verlieren Sie auf mysteriöse Weise Zeilen vom Anfang der Datei an.createInterface()
Sofort werden hinter den Kulissen Zeilen ausgegeben, und der implizit erstellte asynchrone Iteratorconst line of rl
kann erst dann auf diese Zeilen warten , wenn sie erstellt wurden.Altes Thema, aber das funktioniert:
Einfach. Kein externes Modul erforderlich.
quelle
readline is not defined
oder erhaltenfs is not defined
, fügen Sie hinzuvar readline = require('readline');
undvar fs = require('fs');
damit dies funktioniert. Ansonsten süßer, süßer Code. Vielen Dank.Sie können jederzeit Ihren eigenen Zeilenleser rollen. Ich habe dieses Snippet noch nicht bewertet, aber es teilt den eingehenden Stream von Chunks korrekt in Zeilen ohne das nachfolgende '\ n' auf.
Ich habe mir das ausgedacht, als ich an einem schnellen Protokollanalyse-Skript gearbeitet habe, das Daten während der Protokollanalyse sammeln musste, und ich fand es schön, dies mit js und node anstelle von perl oder bash zu versuchen.
Wie auch immer, ich bin der Meinung, dass kleine NodeJS-Skripte in sich geschlossen sein sollten und sich nicht auf Module von Drittanbietern stützen sollten. Nachdem Sie alle Antworten auf diese Frage gelesen haben und jeweils verschiedene Module für die Zeilenanalyse verwenden, könnte eine native 13 SLOC-NodeJS-Lösung von Interesse sein.
quelle
stdin
... es sei denn, ich vermisse etwas.ReadStream
mit erstellenfs.createReadStream('./myBigFile.csv')
und es anstelle vonstdin
readline
Kernmoduls zu lesen .Mit dem Trägermodul :
quelle
var inStream = fs.createReadStream('input.txt', {flags:'r'});
Ihre Syntax ist jedoch sauberer als die dokumentierte Methode zur Verwendung von .on ():carrier.carry(inStream).on('line', function(line) { ...
\r\n
und\n
zu leiten. Wenn Sie jemals mit Testdateien im MacOS-Stil vor OS X arbeiten müssen, werden diese verwendet,\r
und Carrier übernimmt dies nicht. Überraschenderweise schweben immer noch solche Dateien in freier Wildbahn herum. Möglicherweise müssen Sie auch die Unicode-Stückliste (Byte Order Mark) explizit behandeln. Diese wird am Anfang von Textdateien im Einflussbereich von MS Windows verwendet.readline
Kernmoduls zu lesen .Am Ende hatte ich einen massiven Speicherverlust, bei dem Lazy zeilenweise gelesen wurde, als ich versuchte, diese Zeilen zu verarbeiten und in einen anderen Stream zu schreiben, da Drain / Pause / Resume im Knoten funktioniert (siehe: http: // elegantcode) .com / 2011/04/06 / Baby-Schritte-mit-Knoten-js-pumpen-Daten-zwischen-Streams / (ich liebe diesen Kerl übrigens)). Ich habe Lazy nicht genau genug angesehen, um genau zu verstehen, warum, aber ich konnte meinen Lesestream nicht anhalten, um einen Abfluss zu ermöglichen, ohne dass Lazy austrat.
Ich habe den Code geschrieben, um massive CSV-Dateien in XML-Dokumente zu verarbeiten. Den Code finden Sie hier: https://github.com/j03m/node-csv2xml
Wenn Sie die vorherigen Revisionen mit Lazy Line ausführen, ist dies undicht. Die neueste Version leckt überhaupt nicht und Sie können sie wahrscheinlich als Grundlage für einen Leser / Prozessor verwenden. Obwohl ich einige benutzerdefinierte Sachen drin habe.
Bearbeiten: Ich denke, ich sollte auch beachten, dass mein Code mit Lazy gut funktioniert hat, bis ich festgestellt habe, dass ich ausreichend große XML-Fragmente schreibe, die aufgrund einer Notwendigkeit entleeren / pausieren / wieder aufnehmen. Für kleinere Stücke war es in Ordnung.
quelle
readline
Kernmoduls zu lesen .Bearbeiten:
Verwenden Sie einen Transformations-Stream .
Mit einem BufferedReader können Sie Zeilen lesen.
quelle
readline
Kernmoduls zu lesen .Seit ich meine ursprüngliche Antwort gepostet habe, habe ich festgestellt, dass Split ein sehr einfach zu verwendendes Knotenmodul zum Lesen von Zeilen in einer Datei ist. Welches akzeptiert auch optionale Parameter.
Ich habe nicht an sehr großen Dateien getestet. Lassen Sie es uns wissen, wenn Sie dies tun.
quelle
Ich war frustriert über das Fehlen einer umfassenden Lösung dafür und stellte meinen eigenen Versuch zusammen ( git / npm ). Liste der Funktionen kopiert:
NIH? Du entscheidest :-)
quelle
quelle
data
in dem Aufruf,stream.on("data")
jemals mit nur einem Teil eines Multibyte-UTF-8-Zeichens zu beginnen oder zu enden, wieა
esU+10D0
aus den drei Bytes bestehte1
83
90
readline
Kernmoduls zu lesen .Ich wollte das gleiche Problem angehen, im Grunde genommen, was in Perl sein würde:
Mein Anwendungsfall war nur ein eigenständiges Skript, kein Server, daher war die Synchronisierung in Ordnung. Das waren meine Kriterien:
Dies ist ein Projekt für mich, um ein Gefühl für einfachen Skriptcode in node.js zu bekommen und zu entscheiden, wie nützlich er als Ersatz für andere Skriptsprachen wie Perl ist.
Nach überraschend viel Aufwand und ein paar Fehlstarts ist dies der Code, den ich mir ausgedacht habe. Es ist ziemlich schnell, aber weniger trivial als ich erwartet hätte: (Gabel auf GitHub)
Es könnte wahrscheinlich weiter aufgeräumt werden, es war das Ergebnis von Versuch und Irrtum.
quelle
In den meisten Fällen sollte dies ausreichen:
quelle
Generatorbasierter Zeilenleser: https://github.com/neurosnap/gen-readlines
quelle
Wenn Sie eine Datei Zeile für Zeile lesen und in eine andere schreiben möchten:
quelle
Ich hatte das gleiche Problem und fand die obige Lösung, die anderen ähnlich sieht, aber aSync ist und große Dateien sehr schnell lesen kann
Hoffe das hilft
quelle
Ich habe ein kleines Modul, das dies gut kann und von einigen anderen Projekten verwendet wird. Npm readline Beachten Sie, dass es in Knoten v10 ein natives Readline-Modul gibt, sodass ich mein Modul als linebyline https://www.npmjs.com/package/ erneut veröffentlicht habe. Zeile für Zeile
Wenn Sie das Modul nicht verwenden möchten, ist die Funktion sehr einfach:
quelle
Eine andere Lösung besteht darin, die Logik über den sequentiellen Executor nsynjs auszuführen . Es liest Dateien zeilenweise mit dem Knoten-Readline-Modul und verwendet keine Versprechen oder Rekursionen, sodass es bei großen Dateien nicht fehlschlägt. So sieht der Code aus:
Der obige Code basiert auf diesem Beispiel: https://github.com/amaksr/nsynjs/blob/master/examples/node-readline/index.js
quelle
Zwei Fragen, die wir uns bei solchen Operationen stellen müssen, sind:
Lösungen wie
require('fs').readFileSync()
lädt die gesamte Datei in den Speicher. Dies bedeutet, dass die zum Ausführen von Vorgängen erforderliche Speichermenge fast der Dateigröße entspricht. Wir sollten diese für etwas Größeres als vermeiden50mbs
Wir können die von einer Funktion verwendete Speichermenge leicht verfolgen, indem wir diese Codezeilen nach dem Funktionsaufruf platzieren:
Derzeit können Sie bestimmte Zeilen am besten aus einer großen Datei lesen, indem Sie die Readline des Knotens verwenden . Die Dokumentation enthält erstaunliche Beispiele .
Obwohl wir dafür kein Modul eines Drittanbieters benötigen. Wenn Sie jedoch einen Unternehmenscode schreiben, müssen Sie viele Randfälle behandeln. Ich musste ein sehr leichtes Modul namens Apick File Storage schreiben , um all diese Randfälle zu behandeln.
Apick-Dateispeichermodul: https://www.npmjs.com/package/apickfs Dokumentation: https://github.com/apickjs/apickFS#readme
Beispieldatei: https://1drv.ms/t/s!AtkMCsWInsSZiGptXYAFjalXOpUx
Beispiel: Modul installieren
Diese Methode wurde erfolgreich mit bis zu 4 GB dichten Dateien getestet.
big.text ist eine dichte Textdatei mit 163.845 Zeilen und einer Größe von 124 MB. Das Skript zum Lesen von 10 verschiedenen Zeilen aus dieser Datei verwendet nur ungefähr 4,63 MB Speicher. Und es analysiert gültiges JSON kostenlos in Objekte oder Arrays. 🥳 Super !!
Wir können eine einzelne Zeile der Datei oder Hunderte von Zeilen der Datei mit sehr geringem Speicherverbrauch lesen.
quelle
ich benutze das:
Verwenden Sie diese Funktion in einem Stream und hören Sie sich die Zeilenereignisse an, die ausgegeben werden.
GR-
quelle
Während Sie das
readline
Modul wahrscheinlich verwenden sollten, wie in der oberen Antwort angegeben,readline
scheint es eher auf Befehlszeilenschnittstellen als auf das Lesen von Zeilen ausgerichtet zu sein. Es ist auch ein bisschen undurchsichtiger in Bezug auf die Pufferung. (Jeder, der einen Streaming-Line-orientierten Reader benötigt, wird wahrscheinlich die Puffergröße anpassen wollen). Das Readline-Modul besteht aus ~ 1000 Zeilen, während dieses mit Statistiken und Tests 34 Zeilen beträgt.Hier ist eine noch kürzere Version ohne Statistiken mit 19 Zeilen:
quelle
quelle
Ich verpacke die gesamte Logik der täglichen Zeilenverarbeitung als npm-Modul: line-kit https://www.npmjs.com/package/line-kit
quelle
Ich benutze unten Code die gelesenen Zeilen, nachdem ich überprüft habe, dass es kein Verzeichnis ist und es nicht in der Liste der Dateien enthalten ist, muss nicht überprüft werden.
quelle
Ich habe alle oben genannten Antworten durchgesehen, alle verwenden eine Bibliothek von Drittanbietern, um sie zu lösen. Es gibt eine einfache Lösung in der Node-API. z.B
quelle