Menu

Node.js fs.readFile: Dateien lesen (sync, async, Promises)

Eine Datei liest du in Node.js mit fs.readFile (Callback), fs.readFileSync oder await readFile aus fs/promises. Übergib 'utf8', um einen String zu bekommen, und behandle ENOENT, wenn die Datei fehlt.

Diese Seite enthält ausführbare Editoren. Bearbeiten, ausführen und Ausgabe sofort sehen.

fs.readFile(path, 'utf8', callback) liest eine ganze Datei und übergibt ihren Inhalt als String an den Callback. fs.readFileSync(path, 'utf8') gibt den String direkt zurück und wartet, bis das Lesen fertig ist, und await readFile(path, 'utf8') aus fs/promises macht dasselbe, ohne zu blockieren. Lässt du 'utf8' weg, bekommst du statt Text einen Buffer mit den rohen Bytes.

readFile called erscheint zuerst: readFile startet das Lesen nur, und der Callback läuft, sobald der Inhalt bereit ist. Lösch 'utf8', und führ es noch einmal aus: Der Callback bekommt <Buffer 42 75 79 20 6d 69 6c 6b 0a 43 61 6c 6c 20 41 64 61>, die rohen Bytes der Datei.

readFile vs. readFileSync vs. fs/promises

Alle drei lesen dieselbe Datei. Sie unterscheiden sich darin, wie du das Ergebnis bekommst und ob der Rest des Programms wartet.

Die synchrone Zeile erscheint zuerst, weil nichts anderes läuft, bis sie zurückkehrt. Die anderen beiden werden nach dem Hauptcode fertig, in der Reihenfolge, in der ihre Lesevorgänge abgeschlossen sind.

readFileSyncreadFile (Callback)fs/promises readFile
Gibt zurückDen InhaltundefinedEin Promise auf den Inhalt
Blockiert das ProgrammJaNeinNein
FehlerWerden geworfen, nimm try/catchErstes Callback-ArgumentAbgelehntes Promise, try/catch mit await
EinsatzStartcode und SkripteÄlterer Callback-CodeNeuer Code

Nimm readFileSync, wenn du beim Start eine Konfiguration liest oder in einem kurzen Skript. In einem Server hält ein synchrones Lesen jede andere Anfrage an, während die Festplatte arbeitet, nimm dort also die Promise-Variante. Die Seite zu fs/promises behandelt den Rest dieser API.

Eine fehlende Datei behandeln (ENOENT)

Wenn die Datei nicht existiert, hat der Fehler code: 'ENOENT' ("error, no entry"). Prüf err.code, um eine fehlende Datei von anderen Fehlern zu unterscheiden, etwa einem Berechtigungsproblem.

Der erste Aufruf findet keine Datei und fällt auf default settings zurück; der zweite liest dark mode. Wenn du die anderen Fehler erneut wirfst, bleiben echte Probleme sichtbar, statt dass still Standardwerte genutzt werden.

fs.existsSync: Warum du einfach lesen solltest

fs.existsSync(path) gibt true oder false zurück, und es ist verlockend, vor dem Lesen zu prüfen:

if (fs.existsSync('data.txt')) {
    const text = fs.readFileSync('data.txt', 'utf8');
}

Das sind zwei Schritte, wo einer reicht, und die Datei kann zwischen ihnen gelöscht werden, das Lesen kann also trotzdem werfen. Versuch einfach zu lesen und behandle ENOENT wie oben. existsSync ist in Ordnung, wenn du nur wissen musst, ob etwas existiert, und es nicht öffnest, zum Beispiel um zu entscheiden, ob ein Ordner angelegt werden soll.

Eine JSON-Datei lesen

Lies den Text und parse ihn dann mit JSON.parse. Eine Datei mit Syntaxfehler wirft einen SyntaxError, lass das also im selben try.

Es gibt 3001 und boolean aus: Nach dem Parsen haben die Werte ihre JSON-Typen. require('./config.json') funktioniert auch, cacht aber das Ergebnis, ein zweites require gibt also das alte Objekt zurück, selbst wenn sich die Datei geändert hat.

Eine Datei zeilenweise lesen

Eine Datei, die in den Speicher passt, liest du ganz und teilst sie am Zeilenumbruch. Filter den leeren String heraus, den ein abschließender Zeilenumbruch hinterlässt.

Das Split ergibt 4 Elemente, das letzte leer, deshalb gibt die Schleife drei nummerierte Zeilen aus. Unter Windows geschriebene Dateien beenden Zeilen mit \r\n; teil an /\r?\n/, um beides abzudecken.

Ein Log mit mehreren Gigabyte passt nicht in den Speicher. Streame es stattdessen, damit immer nur eine Zeile gehalten wird:

const fs = require('fs');
const readline = require('readline');

async function main() {
    const rl = readline.createInterface({
        input: fs.createReadStream('big.log'),
        crlfDelay: Infinity,
    });
    for await (const line of rl) {
        console.log(line);
    }
}
main();

Häufige Fehler

Das Ergebnis außerhalb des Callbacks nutzen. const text = fs.readFile(...) ist undefined. Der Inhalt existiert nur im Callback oder nach await.

Das Encoding vergessen. Ohne 'utf8' bekommst du einen Buffer, und data.split('\n') wirft data.split is not a function. Übergib das Encoding immer, wenn du Text willst.

Pfade relativ zum falschen Ordner. 'data.txt' wird dort gesucht, wo node gestartet wurde. Nimm path.join(__dirname, 'data.txt') für eine Datei, die neben deinem Skript liegt.

Häufig gestellte Fragen

Warum gibt fs.readFile undefined zurück?

fs.readFile gibt den Inhalt nicht zurück. Es startet das Lesen und ruft deinen Callback später mit (err, data) auf. Nutz die Daten im Callback, ruf readFileSync auf oder warte mit await auf die Promise-Variante.

Wo sucht Node einen relativen Pfad wie 'data.txt'?

Im aktuellen Arbeitsverzeichnis, also dem Ordner, aus dem du node gestartet hast, nicht im Ordner des Skripts. Um eine Datei neben dem Skript zu lesen, bau den Pfad mit path.join(__dirname, 'data.txt').

Kann fs.readFile eine Datei von einer URL lesen?

Nein, es liest nur aus dem Dateisystem. Für eine Datei über HTTP nimm fetch und dann await res.text().

Wie groß darf eine Datei für readFile sein?

Es lädt die ganze Datei in den Speicher, für Konfigurationen, Templates und kleine Datendateien ist das also kein Problem. Dateien mit Hunderten Megabyte liest du stückweise mit fs.createReadStream.

Illustration der Programmiersprachen bei Coddy

Lerne mit Coddy zu programmieren

Los geht's