Node verfügt über eine Reihe von Datenstrom -APIs, mit denen Dateien wie Verarbeitung von Netzwerkströmen verarbeitet werden können, die sehr bequem zu verwenden sind. Er ermöglicht jedoch nur, dass Dateien nacheinander verarbeitet werden und keine Dateien zufällig lesen und schreiben können. Daher müssen einige zugrunde liegende Dateisystemvorgänge verwendet werden.
Dieses Kapitel behandelt die Grundlagen der Dateiverarbeitung, einschließlich des Öffnens einer Datei, dem Lesen eines Teils einer Datei, des Schreibens von Daten und zum Schließen einer Datei.
Viele der Datei -APIs des Knotens sind fast eine Nachbildung der entsprechenden Datei -API in UNIX (POSIX). Beispielsweise wird die Verwendung von Dateideskriptoren verwendet. Genau wie in UNIX ist der Dateideskriptor auch eine Ganzzahlnummer im Knoten, die den Index einer Entität in der Prozessdateideskriptor -Tabelle darstellt.
Es gibt 3 Sonderdateideskriptoren - 1, 2 und 3.. Sie stellen Standardeingangs-, Standardausgabe- und Standardfehlerdateideskriptor dar. Die Standardeingabe ist, wie der Name schon sagt, ein schreibgeschützter Stream, mit dem Prozesse Daten aus dem Konsolen- oder Prozesskanal lesen. Standardausgabe und Standardfehler sind Dateideskriptoren, die nur zum Ausgabe von Daten verwendet werden. Sie werden häufig verwendet, um Daten an Konsolen, andere Prozesse oder Dateien auszugeben. Standardfehler sind für die Ausgabe der Fehlermeldung verantwortlich, während die Standardausgabe für die normale Prozessausgabe verantwortlich ist.
Sobald der Prozess gestartet wurde, können diese Dateideskriptoren verwendet werden und haben keine entsprechenden physischen Dateien. Sie können Daten nicht an einem zufälligen Ort lesen und schreiben. (Anmerkung des Übersetzers: Der Originaltext ist, dass Sie bestimmte Positionen in der Datei schreiben und aus lesen können. Abhängig vom Kontext kann der Autor möglicherweise weniger "nicht" geschrieben haben.
Gewöhnliche Dateien unterliegen dieser Einschränkung nicht. Zum Beispiel können Sie im Knoten Dateien erstellen, die nur Daten an den Schwanz anhängen und auch Dateien erstellen können, die zufällige Positionen lesen und schreiben.
Fast alle dateibezogenen Operationen beinhalten die Verarbeitung von Dateipfaden. In diesem Kapitel wird zuerst diese Toolfunktionen vorgestellt und dann eingehende Lesen, Schreiben und Datenvorgänge der Datei erläutert.
Prozessdateipfad
Dateipfade sind in zwei Typen unterteilt: relative Pfade und absolute Pfade und sie werden verwendet, um bestimmte Dateien darzustellen. Sie können Dateipfade zusammenführen, Dateinameninformationen extrahieren und sogar feststellen, ob die Datei vorliegt.
Im Knoten können Sie Zeichenfolgen verwenden, um Dateipfade zu manipulieren, aber das kompliziert das Problem. Sie möchten beispielsweise verschiedene Teile des Pfades anschließen, einige Teile enden mit "/", aber einige tun dies nicht, und der Pfadsplitter kann in verschiedenen Betriebssystemen auch unterschiedlich sein. Wenn Sie sie also verbinden, ist der Code sehr wortreich und problematisch.
Glücklicherweise verfügt Node über ein Modul namens Pfad, mit dem Sie die Pfade standardisieren, verbinden, analysieren, von absoluten Pfaden auf relative Pfade konvertieren, verschiedene Teile von Informationen aus den Pfaden extrahieren und feststellen, ob die Datei existiert. Im Allgemeinen ist das Pfadmodul eigentlich nur eine String -Verarbeitung, und es wird nicht zum Dateisystem zur Überprüfung geleitet (Path.Exists -Funktionsausnahme).
Standardisierung von Pfaden
Es ist normalerweise eine gute Idee, sie vor dem Speichern oder Verwenden von Pfaden zu normalisieren. Beispielsweise sollten Dateipfade, die von Benutzerneingaben oder Konfigurationsdateien oder durch zwei oder mehr Pfade verbundenen Pfade erhalten werden, im Allgemeinen standardisiert werden. Ein Pfad kann unter Verwendung der Normalisierungsfunktion des Pfadmoduls normalisiert werden und auch "..", "." // ". Zum Beispiel:
Die Codekopie lautet wie folgt:
var path = require ('path');
path.normalize ('/foo/bar // baz/asdf/quux/..');
// => '/foo/baz/baz/asdf'
Verbindungsweg
Mit der Funktion path.join () können Sie so viele Pfadketten verkettet. Sie können einfach alle Pfadzeichenfolgen in die Folge der join () -Funktion übergeben:
Die Codekopie lautet wie folgt:
var path = require ('path');
path.join ('/foo', 'bar', 'baz/asdf', 'quux', '..');
// => '/foo/baz/baz/asdf'
Wie Sie sehen können, normalisieren Path.Join () den Pfad automatisch im Inneren.
Weg
Verwenden Sie Pfad.Resolve (), um mehrere Pfade in einen absoluten Pfad aufzulösen. Seine Funktion ist wie "CD" -Operationen einzeln auf diesen Pfaden. Im Gegensatz zu den Parametern des CD -Befehls können diese Pfade Dateien sein, und sie müssen im wirklichen Leben nicht existieren - die Methode des Pfades.
Zum Beispiel:
Die Codekopie lautet wie folgt:
var path = require ('path');
path.resolve ('/foo/bar', './baz');
// =>/foo/baz/baz
path.resolve ('/foo/bar', '/tmp/file/');
// =>/tmp/Datei
Wenn das Analyseergebnis kein absoluter Weg ist, fügt Path.Resolve () das aktuelle Arbeitsverzeichnis als Weg zum Parsing -Ergebnis an, zum Beispiel:
Die Codekopie lautet wie folgt:
path.resolve ('wwwroot', 'static_files/png/', '../gif/image.gif');
// Wenn das aktuelle Arbeitsverzeichnis/zu Hause/mich/Node ist, wird es zurückkehren
// => /home/myself/node/wwwroot/static_files/gif/image.gif '
Berechnen Sie die relativen Pfade von zwei absoluten Pfaden
path.relative () kann Ihnen sagen, ob Sie beispielsweise von einer absoluten Adresse zu einer anderen absoluten Adresse springen:
Die Codekopie lautet wie folgt:
var path = require ('path');
path.relative ('/data/orandea/test/aaa', '/data/orandea/impl/bbb');
// => ../../impl/bbb
Daten aus dem Pfad extrahieren
Nehmen Sie den Pfad "/foo/bar/myFile.txt" als Beispiel. Wenn Sie den gesamten Inhalt des übergeordneten Verzeichnisses (/Foo/Bar) erhalten oder andere Dateien desselben Ebenenverzeichnisses lesen möchten, müssen Sie den Pfad verwenden.
Die Codekopie lautet wie folgt:
var path = require ('path');
path.dirname ('/foo/bar/baz/asdf/quux.txt');
// =>/foo/baz/baz/asdf
Oder wenn Sie den Dateinamen aus dem Dateipfad abrufen möchten, dh dem letzten Teil des Dateipfads, können Sie die Funktion path.Basename verwenden:
Die Codekopie lautet wie folgt:
var path = require ('path');
path.basename ('/foo/bar/baz/asdf/quux.html')
// => quux.html
Der Dateipfad kann auch eine Dateierweiterung enthalten, normalerweise den Teil der Zeichenfolge nach dem letzten "." Zeichen im Dateinamen.
Path.Basename kann auch eine Erweiterungsname -Zeichenfolge als zweiter Parameter akzeptieren, damit der zurückgegebene Dateiname automatisch die Erweiterung entfernt und nur den Namen der Datei zurückgibt:
Die Codekopie lautet wie folgt:
var path = require ('path');
path.basename ('/foo/bar/baz/asdf/quux.html', '.html');
// => quux
Dazu müssen Sie zunächst die Dateierweiterung kennen. Sie können path.extname () verwenden, um die Erweiterung zu erhalten:
Die Codekopie lautet wie folgt:
var path = require ('path');
path.extName ('/a/b/index.html');
// => '.html'
path.extName ('/a/bc/index');
// => ''
path.extName ('/a/bc/.');
// => ''
path.extName ('/a/bc/d.');
// => '.'
Überprüfen Sie, ob der Weg existiert
Bisher haben die oben genannten Pfadverarbeitungsvorgänge nichts mit dem zugrunde liegenden Dateisystem zu tun, sondern nur einige String -Operationen. Manchmal müssen Sie jedoch feststellen, ob ein Dateipfad existiert. Manchmal müssen Sie beispielsweise feststellen, ob eine Datei oder ein Verzeichnis vorhanden ist. Wenn es nicht vorhanden ist, können Sie path.EXSITS () verwenden:
Die Codekopie lautet wie folgt:
var path = require ('path');
Path.Exists ('/etc/passwd', Funktion (existiert) {{
console.log ('existiert:', existiert);
// => true
});
path.exists ('/do_not_exist', function (existiert) {
console.log ('existiert:', existiert);
// => false
});
HINWEIS: Ab der NODE0.8 -Version existiert das Pfadmodul zum FS -Modul und wurde zu FS.xisten. Mit Ausnahme des Namespace hat sich nichts anderes geändert:
Die Codekopie lautet wie folgt:
var fs = fordert ('fs');
fs.exists ('/do_not_exist', function (existiert) {
console.log ('existiert:', existiert);
// => false
});
path.exists () ist eine E/A -Operation. Da es asynchron ist, ist eine Rückruffunktion erforderlich. Wenn die E/A -Operation zurückgibt, wird die Rückruffunktion aufgerufen und das Ergebnis an sie weitergegeben. Sie können auch seine synchrone Version von path.existssync () verwenden, die dieselbe Funktion hat, außer dass es die Rückruffunktion nicht aufgerufen, sondern das Ergebnis direkt zurückgibt:
Die Codekopie lautet wie folgt:
var path = require ('path');
path.existsSync ('/etc/passwd');
// => true
Einführung in das FS -Modul
Das FS -Modul enthält alle zugehörigen Funktionen für die Dateiabfrage und -verarbeitung. Mit diesen Funktionen können Sie Dateieninformationen abfragen, Dateien lesen, schreiben und schließen. Importieren Sie das FS -Modul wie dieses:
Die Codekopie lautet wie folgt:
var fs = erfordern ('fs')
Informationen zur Abfragedatei
Manchmal müssen Sie möglicherweise Dateiinformationen wie Dateigröße, Erstellungsdatum oder Berechtigungen kennen. Sie können die Fs.Stath -Funktion verwenden, um die Meta -Informationen einer Datei oder eines Verzeichnisses abzufragen:
Die Codekopie lautet wie folgt:
var fs = fordert ('fs');
fs.Stat ('/etc/passwd', Funktion (err, statistics) {
if (err) {throw err;}
console.log (Statistiken);
});
Dieser Code -Snippet hat eine ähnliche Ausgabe wie folgt
Die Codekopie lautet wie folgt:
{Dev: 234881026,
INO: 95028917,
Modus: 33188,
nlink: 1,,
UID: 0,
gid: 0,
RDEV: 0,,
Größe: 5086,
BlkSize: 4096,
Blöcke: 0,
Ähnlich: Fr, 18. November 2011 22:44:47 GMT,
Mtime: Thu, 08. September 2011 23:50:04 GMT,
CTime: Thu, 08. September 2011 23:50:04 GMT}
1. Der Aufruf fs.stat () übergibt eine Instanz der Statistikklasse als Parameter an seine Rückruffunktion. Sie können die Statistikinstanz wie folgt verwenden:
2.Stat.s.isfile () - Geben Sie True zurück, wenn es sich um eine Standarddatei handelt, kein Verzeichnis, ein Buchse, ein symbolischer Link oder ein Gerät, ansonsten falsch
3.Stats.isdiretory () - Wenn es sich um ein Verzeichnis handelt, retue tue, ansonsten falsch
4.Stats.isblockDevice () - RECHT TRUE, wenn es sich um ein Blockgerät handelt. In den meisten Unix -Systemen befindet sich das Blockgerät normalerweise im /dev -Verzeichnis.
5.Stats.iShracterDevice () - RECHT TRUE, wenn es sich um ein Zeichengerät handelt
6.Stats.ISSYMBOLICKLINK () - Geben Sie True zurück, wenn es sich um einen Dateilink handelt
7.Staten.isisfifo () - Wenn es sich um ein FIFO (eine spezielle Art von Unix namens Pipe) handelt
8.Stats.Issocket () - Wenn es sich um einen Unix -Socket handelt (TODO: Googe It)
Öffnen Sie die Datei
Vor dem Lesen oder Verarbeiten einer Datei müssen Sie zuerst die Funktion fs.open verwenden, um die Datei zu öffnen, und dann wird die von Ihnen angegebene Rückruffunktion aufgerufen und den Deskriptor der Datei abgerufen. Später können Sie diesen Dateideskriptor verwenden, um die geöffnete Datei zu lesen und zu schreiben:
Die Codekopie lautet wie folgt:
var fs = fordert ('fs');
fs.open ('/path/to/file', 'r', function (err, fd) {
// Got FD -Dateideskriptor
});
Der erste Parameter von fs.open ist der Dateipfad, und der zweite Parameter ist einige Tags, mit denen angezeigt wird, in welchem Modus die Datei geöffnet wird. Diese Tags können R, R+, W, W+, A oder A+sein. Unten finden Sie eine Erklärung dieser Tags (aus der Fopen -Seite der Unix -Dokumentation)
1.R - Öffnen Sie die Datei im schreibgeschützten Modus, der anfängliche Speicherort des Datenstroms beginnt in der Datei
2.R+ - Öffnen Sie die Datei auf lesbare und schriftliche Weise, und der anfängliche Ort des Datenstroms beginnt in der Datei
3.W - Wenn die Datei vorhanden ist, löschen Sie die Dateilänge um 0, dh der Inhalt der Datei geht verloren. Wenn es nicht existiert, versuchen Sie es zu erstellen. Der anfängliche Ort des Datenstroms beginnt in der Datei
4.W+ - Öffnen Sie die Datei auf lesbare und schriftliche Weise. Wenn die Datei nicht vorhanden ist, versuchen Sie, sie zu erstellen. Wenn die Datei vorhanden ist, löschen Sie die Dateilänge um 0, dh der Inhalt der Datei geht verloren. Der anfängliche Ort des Datenstroms beginnt in der Datei
5.A - Öffnen Sie die Datei nur schreibein. Wenn die Datei nicht vorhanden ist, versuchen Sie, sie zu erstellen. Der anfängliche Ort des Datenstroms befindet sich am Ende der Datei. Jeder nachfolgende Schreibvorgang wendet die Daten an der Rückseite der Datei an.
6.A+ - Öffnen Sie die Datei auf lesbare und schriftliche Weise. Wenn die Datei nicht vorhanden ist, versuchen Sie, sie zu erstellen. Der anfängliche Ort des Datenstroms befindet sich am Ende der Datei. Jede nachfolgende Schreibvor Operation wird die Daten an der Rückseite der Datei angehängt.
Lesen Sie die Datei
Sobald die Datei geöffnet ist, können Sie mit dem Lesen des Dateiinhalts beginnen, aber bevor Sie beginnen, müssen Sie einen Puffer erstellen, um die Daten zu platzieren. Dieses Pufferobjekt wird als Parameter an die Fs.read -Funktion übergeben und mit Daten von Fs.read gefüllt.
Die Codekopie lautet wie folgt:
var fs = fordert ('fs');
fs.open ('./ my_file.txt', 'r', Funktion geöffnet (err, fd) {
if (err) {throw err}
var readbuffer = neuer Puffer (1024),
bufferOffset = 0,,
pufferLength = readbuffer.length,
fileposition = 100;
fs.read (fd,
ReadBuffer,
Pufferoffset,
Pufferlänge,
Fileposition,
Funktion read (err, readBytes) {
if (err) {throw ers; }
console.log ('einfach read' + readBytes + 'bytes');
if (readBytes> 0) {
console.log (readbuffer.slice (0, readBytes));
}
});
});
Der obige Code versucht eine Datei zu öffnen. Nach erfolgreichem Öffnen (Aufruf der geöffneten Funktion) beginnt mit der Aufforderung, die nächsten 1024 Datenbytes aus dem 100. Byte des Dateistroms (Zeile 11) zu lesen.
Der letzte Parameter von fs.read () ist eine Rückruffunktion (Zeile 16). Wenn die folgenden drei Situationen auftreten, wird es genannt:
1. Ein Fehler trat auf
2. Die Daten wurden erfolgreich gelesen
3.. Keine Daten zum Lesen zum Lesen
Wenn ein Fehler auftritt, liefert der erste Parameter (ERR) die Rückruffunktion mit einem Objekt, das die Fehlermeldung enthält. Andernfalls ist dieser Parameter null. Wenn die Daten erfolgreich gelesen werden, gibt der zweite Parameter (ReadBytes) die Größe der im Puffer gelesenen Daten an. Wenn der Wert 0 ist, bedeutet dies, dass das Ende der Datei erreicht wurde.
HINWEIS: Sobald das Pufferobjekt an fs.open () übergeben wurde, wird die Steuerung des Pufferobjekts auf den Befehl read übertragen. Nur wenn die Rückruffunktion aufgerufen wird, wird Ihnen die Steuerung des Pufferobjekts an Sie zurückgegeben. Lesen und schreiben oder lassen Sie andere Funktionsaufrufe dieses Pufferobjekt nicht. Andernfalls können Sie unvollständige Daten lesen, und schlimmer noch, Sie können Daten gleichzeitig in dieses Pufferobjekt schreiben.
Schreiben Sie eine Datei
Übergeben Sie ein Pufferobjekt, das Daten enthält, indem Sie sie an fs.write () übergeben, und schreiben Sie Daten in eine geöffnete Datei:
Die Codekopie lautet wie folgt:
var fs = fordert ('fs');
fs.open ('./ my_file.txt', 'a', Funktion geöffnet (err, fd) {
if (err) {throw ers; }
var writeBuffer = neuer Buffer ('Schreiben dieser Zeichenfolge'),
Pufferposition = 0,,
bufferLength = writeBuffer.length, fileposition = null;
fs.write (fd,
WriteBuffer,
Pufferposition,
Pufferlänge,
Fileposition,
Funktion write (err, geschrieben) {
if (err) {throw ers; }
console.log ('geschrieben' + geschrieben + 'bytes');
});
});
In diesem Beispiel versucht die zweite Zeile von Code, eine Datei im Append -Modus (a) zu öffnen, und dann die siebte Codezeile (Anmerkung des Übersetzers: Originaltext ist 9) Daten in die Datei. Das Pufferobjekt muss von mehreren Informationen als Parameter begleitet werden:
1. Pufferdaten
2. Wo beginnen die Daten, die in dem Puffer geschrieben werden sollen?
3. Die zu schriftliche Datenlänge
4. Wo schreiben Sie die Daten in die Datei?
5. Die Rückruffunktion, die nach Abschluss der Operation geschrieben wurde
In diesem Beispiel ist der Parameter von FilePoStion Null, was bedeutet, dass die Schreibfunktion die Daten an den aktuellen Speicherort des Dateizeigers schreibt. Da es sich um eine im Append -Modus geöffnete Datei handelt, befindet sich der Dateizeiger am Ende der Datei.
Verwenden Sie wie Lesen von Operationen nicht, welches eingehende Pufferobjekt während der Ausführung von Fs.Write verwendet wird. Sobald Fs.Write ausgeführt wird, erlangt es die Kontrolle über dieses Pufferobjekt. Sie können nur warten, bis die Rückruffunktion aufgerufen wird, bevor Sie sie wiederverwenden.
Schließen Sie die Datei
Möglicherweise haben Sie festgestellt, dass alle Beispiele in diesem Kapitel bisher keinen Code haben, um die Datei zu schließen. Da sie nur kleine und einfache Beispiele sind, wenn sie nur einmal verwendet werden, stellt das Betriebssystem sicher, dass alle Dateien geschlossen werden, wenn der Knotenvorgang endet.
In der tatsächlichen Anwendung möchten Sie jedoch sicherstellen, dass Sie sie schließen. Dazu müssen Sie alle diese offenen Dateideskriptoren verfolgen und dann fs.close (fd [, callback]) aufrufen, wenn sie nicht mehr verwendet werden, um sie schließlich zu schließen. Wenn Sie nicht aufpassen, ist es leicht, einen bestimmten Dateideskriptor zu verpassen. Das folgende Beispiel enthält eine Funktion namens OpenAndWritetoSystemLog, die zeigt, wie Dateien sorgfältig geschlossen werden können:
Die Codekopie lautet wie folgt:
var fs = fordert ('fs');
Funktion OpenAndWritetosystemLog (WriteBuffer, Callback) {
fs.open ('./ my_file', 'a', Funktion geöffnet (err, fd) {
if (err) {return callback (err); }
Funktion notifyError (err) {
fs.close (fd, function () {
Rückruf (arr);
});
}
var bufferOffset = 0,,
pufferLength = writeBuffer.length,
fileposition = null;
fs.write (fd, writeBuffer, bufferOffset, pufferLength, fileposition,
Funktion write (err, geschrieben) {
if (err) {return musifyError (err); }
fs.close (fd, function () {
Rückruf (arr);
});
}
);
});
}
OpenAndWritetosystemLog (
neuer Puffer ('Schreiben dieser Zeichenfolge'),
Funktion DURDE (ERR) {
if (err) {
console.log ("Fehler beim Öffnen und Schreiben:", err.message);
zurückkehren;
}
console.log ('alles ohne Fehler gemacht');
}
);
Hier wird eine Funktion namens OpenAndWritetoSystemLog bereitgestellt, die ein Pufferobjekt akzeptiert, das die zu geschriebenen Daten enthält, und eine Rückruffunktion, die nach Abschluss des Vorgangs aufgerufen wird oder ein Fehler auftritt. Wenn ein Fehler auftritt, enthält der erste Parameter der Rückruffunktion dieses Fehlerobjekt.
Beachten Sie, dass die interne Funktion notifyErrror, die die Datei schließt und einen auftritt, auftritt.
Hinweis: Bis dahin wissen Sie, wie Sie die zugrunde liegenden Atomoperationen zum Öffnen, Lesen, Schreiben und Schließen von Dateien verwenden. Node verfügt jedoch auch über einen fortgeschritteneren Satz von Konstruktoren, mit denen Sie Dateien einfacher verarbeiten können.
Sie möchten beispielsweise einen sicheren Weg verwenden, um zwei oder mehr Schreibvorgänge gleichzeitig an eine Datei anzugreifen, und Sie können WriteStream verwenden.
Wenn Sie einen bestimmten Bereich einer Datei lesen möchten, können Sie auch ReadStream verwenden. Diese beiden Anwendungsfälle werden in Kapitel 9 "Lesen und Schreiben von Datenverschreibungen" eingeführt.
Zusammenfassung
Wenn Sie eine Datei verwenden, müssen Sie in den meisten Fällen Dateipfadinformationen verarbeiten und extrahieren. Durch die Verwendung des Pfadmoduls können Sie Pfade anschließen, Pfade standardisieren, Pfadunterschiede berechnen und relative Pfade in absolute Pfade umwandeln. Sie können Pfadkomponenten wie Erweiterungen, Dateinamen, Verzeichnisse usw. extrahieren.
Der Knoten bietet im FS -Modul eine Reihe von zugrunde liegenden APIs zum Zugriff auf das Dateisystem, und die zugrunde liegende API verwendet Dateideskriptoren, um Dateien zu manipulieren. Sie können die Datei mit fs.open öffnen, die Datei mit fs.write schreiben, die Datei mit fs.read lesen und die Datei mit Fs.Close schließen.
Wenn ein Fehler auftritt, sollten Sie immer die korrekte Fehlerbehandlungslogik verwenden, um die Datei zu schließen - um sicherzustellen, dass diese geöffneten Dateideskriptoren vor Rückgabe des Anrufs geschlossen werden.