Quiz: NodeJS‑IO‑Meisterschaft
Testen Sie Ihr Wissen zu Dateien, Streams und Buffern
Bereit, in die Welt von NodeJS IO einzutauchen? 🌊
Dieses Quiz prüft Ihr Verständnis der IO‑Operationen von Node, von einfachen Dateisystem‑Aufrufen bis hin zu fortgeschrittenen Streaming‑Konzepte. Wir behandeln Buffer, Kodierung und bewährte Vorgehensweisen für eine effiziente Datenverarbeitung.
Mal sehen, wie gut Sie Ihre Streams im Vergleich zu Ihren Buffern kennen! 🚀
Was macht dieser Code?
const buf = Buffer.alloc(5);console.log(buf);Buffer.alloc(size) erstellt einen neuen Buffer mit der angegebenen Größe, gefüllt mit Nullen.
Die Ausgabe ist: <Buffer 00 00 00 00 00>
Wenn du einen Buffer mit zufälligen Daten erstellen willst, benutze Buffer.allocUnsafe(5).
Was wird das ausgeben?
const buf = Buffer.from([65]);console.log(buf.toString());Die Zahlen im Array repräsentieren ASCII‑Codes:
- 65: ‘A’
toString() wandelt diese Bytes standardmäßig mithilfe der UTF‑8‑Kodierung in ihre String‑Darstellung um.
Wie lautet die Ausgabereihenfolge?
import fs from 'fs';fs.readFile('test.txt', 'utf8', (err, data) => { console.log(data);});console.log('Done');Da readFile asynchron ist, wird der Code weiter ausgeführt, während die Datei gelesen wird.
Deshalb wird “Done” vor dem Dateinhalt ausgegeben.
Um zuerst auf das Lesen der Datei zu warten, könntest du die Promise-basierte Version verwenden:
import { promises as fs } from 'fs';
async function read() { const data = await fs.readFile('test.txt', 'utf8'); console.log(data); console.log('Done');}Was gibt fs.readFileSync() standardmäßig zurück?
import fs from 'fs';const content = fs.readFileSync('test.txt');fs.readFileSync() gibt standardmäßig einen Buffer zurück, wenn keine Kodierung angegeben ist. Wenn du einen String möchtest, musst du entweder:
- Eine Kodierung angeben:
fs.readFileSync('test.txt', 'utf8') - Den Buffer konvertieren:
content.toString()
Welche Menge von Ereignissen wird üblicherweise mit lesbaren Streams verwendet?
Lesbare Streams geben mehrere wichtige Ereignisse aus:
- ‘data’: Wenn Daten zum Lesen verfügbar sind
- ‘end’: Wenn keine Daten mehr zum Lesen vorhanden sind
- ‘error’: Wenn ein Fehler auftritt
- ‘close’: Wenn der Stream und die zugrunde liegende Ressource geschlossen wurden
const readable = fs.createReadStream('file.txt');readable.on('data', chunk => console.log(chunk));readable.on('end', () => console.log('Done!'));Was macht dieser Code?
import fs from 'fs';const readable = fs.createReadStream('source.txt');const writable = fs.createWriteStream('dest.txt');readable.pipe(writable);pipe() verbindet einen lesbaren Stream mit einem schreibbaren Stream, verwaltet automatisch den Backpressure und kopiert Daten in Stücke, ohne die gesamte Datei in den Speicher zu laden.
Das ist speichereffizient für große Dateien im Vergleich zu fs.readFile() gefolgt von fs.writeFile().
Was bewirkt die Option recursive?
import fs from 'fs';fs.mkdirSync('./a/b/c', { recursive: true });Die Option recursive: true erstellt übergeordnete Verzeichnisse, falls sie nicht existieren.
Ohne diese Option würde der Versuch, ’./a/b/c’ zu erstellen, einen Fehler werfen, wenn ’./a’ oder ’./a/b’ nicht existieren.
Das ist ähnlich dem Shell‑Befehl mkdir -p.
Was wird das ausgeben?
import { Transform } from 'stream';const upperCase = new Transform({ transform(chunk, encoding, callback) { callback(null, chunk.toString().toUpperCase()); }});process.stdin .pipe(upperCase) .pipe(process.stdout);// Input: "hello world"Transform-Streams verändern Daten, während sie hindurchfließen. Hier wird jedes Chunk:
- In einen String konvertiert
- In Großbuchstaben umgewandelt
- An stdout weitergeleitet
Das erzeugt eine Pipeline, die die gesamte Eingabe in Großbuchstaben umwandelt.
Wie oft wird fs.watch() garantiert ausgelöst, wenn eine Datei geändert wird?
import fs from 'fs';fs.watch('test.txt', (eventType, filename) => { console.log(`${filename} was changed`);});// Then modify test.txt oncefs.watch() ist nicht garantiert, exakt einmal pro logischer Dateiveränderung auszulösen. Es wird häufig mehrfach ausgelöst, weil viele Texteditoren:
- In eine temporäre Datei speichern
- Sie in die Zieldatei umbenennen
Für zuverlässigeres Beobachten solltest du erwägen:
- Das
chokidar‑Paket - Das Debouncen des Callbacks
fs.watchFile()zu verwenden (obwohl es weniger effizient ist)
Was ist die Ausgabe?
const buf1 = Buffer.from('Hello');const buf2 = Buffer.from('Hello');console.log(buf1 === buf2);Buffer werden per Referenz verglichen, nicht nach Wert. Obwohl sie dieselben Daten enthalten, sind sie unterschiedliche Objekte.
Um Buffer-Inhalte zu vergleichen, verwende:
buf1.equals(buf2) // true// orBuffer.compare(buf1, buf2) === 0 // trueWas ist der Hauptzweck von Stream-Backpressure?
Backpressure ist ein Mechanismus, der Speicherüberlauf verhindert, indem er das Lesen pausiert, wenn das Schreibende nicht mithalten kann.
Beispiel für manuelle Backpressure:
readable.on('data', (chunk) => { const canContinue = writable.write(chunk); if (!canContinue) { readable.pause(); writable.once('drain', () => readable.resume()); }});pipe() erledigt das automatisch!
Was macht dieser Code?
import fs from 'fs';fs.symlinkSync('target.txt', 'link.txt');symlinkSync erstellt einen symbolischen Link (wie eine Verknüpfung) zur Zieldatei.
Wichtigste Unterschiede zu Hardlinks:
- Kann auf Verzeichnisse verlinken
- Kann Dateisysteme übergreifen
- Bricht, wenn das Ziel gelöscht wird
So erstellst du stattdessen einen Hardlink:
fs.linkSync('target.txt', 'hardlink.txt');In welchen Modi können Node.js‑Streams arbeiten?
Streams können arbeiten in:
- Binärmodus (Standard): für Buffer und Strings
- Objektmodus: für beliebige JavaScript‑Werte
Beispiel für Objektmodus:
import { Transform } from 'stream';const objectStream = new Transform({ objectMode: true, transform(chunk, encoding, callback) { callback(null, { value: chunk }); }});Welchen Typ hat der fd‑Parameter in diesem Callback?
import fs from 'fs';fs.open('test.txt', 'r', (err, fd) => { console.log(typeof fd);});Dateideskriptoren sind Zahlen, die geöffnete Dateien im Betriebssystem eindeutig identifizieren.
Die ersten drei Dateideskriptoren sind reserviert:
- 0: stdin
- 1: stdout
- 2: stderr
Denk immer daran, Dateideskriptoren zu schließen:
fs.close(fd, (err) => { if (err) throw err;});Wie viele Bytes benötigt dieser String in UTF‑8?
const str = "Hello 🌍";const buf = Buffer.from(str);console.log(buf.length);In UTF‑8:
- ASCII‑Zeichen (wie ‘Hello ’) benötigen jeweils 1 Byte
- Das Erde‑Emoji 🌍 benötigt 4 Bytes
Also: 5 (Hello) + 1 (Leerzeichen) + 4 (🌍) = 10 Bytes
Um die Bytes zu sehen:
console.log(buf); // <Buffer 48 65 6c 6c 6f 20 f0 9f 8c 8d>Ich hoffe,Ihnen hat das Testen Ihres NodeJS‑IO‑Wissens gefallen! Noch mehr? Schauen Sie sich meine Quiz‑Sammlung für weitere Aufgaben an!