Start · Sprachen · JavaScript · Referenz · new TextDecoderStream()

new TextDecoderStream()

Methode

Erzeugt einen <code>TextDecoderStream</code>, der einen Strom binärer Daten (z. B. <code>Uint8Array</code>-Chunks) fortlaufend in Zeichenketten dekodiert.

seit JavaScript Baseline 2023: Chrome 71, Edge 79, Firefox 105, Sa Kategorie: webapi

Signatur

new TextDecoderStream(label, options)

Beschreibung

Der Konstruktor TextDecoderStream() erstellt einen Transform-Stream mit den Eigenschaften readable und writable. Auf der schreibbaren Seite nimmt er Binärdaten (ArrayBuffer, TypedArray oder DataView) entgegen, auf der lesbaren Seite liefert er die dekodierten Zeichenketten. Er ist damit das Stream-Gegenstück zu TextDecoder.

Typischer Einsatz: Man leitet den Rumpf einer fetch()-Antwort per response.body.pipeThrough(new TextDecoderStream()) um und verarbeitet Text schrittweise, während er noch ankommt – etwa bei großen Logdateien, NDJSON oder Server-Sent-ähnlichen Streams und Token-Streams von KI-APIs. Auch bei der Web Serial API oder Dateien (Blob.stream()) ist er hilfreich.

Der entscheidende Vorteil gegenüber einem manuellen TextDecoder.decode() pro Chunk: Mehrbyte-Zeichen (z. B. UTF-8-Umlaute oder Emojis), die über zwei Chunk-Grenzen verteilt sind, werden korrekt zusammengesetzt. Intern entspricht das einem decode(chunk, { stream: true }) mit abschließendem Flush.

Parameter

Name Typ Default Beschreibung
$label string "utf-8" Bezeichnung der Zeichenkodierung, z. B. "utf-8", "iso-8859-1", "windows-1252", "utf-16le". Ungültige Bezeichnungen lösen einen RangeError aus.
$options object {} Optionales Konfigurationsobjekt.
$options.fatal boolean false Bei true führt ungültige Bytefolge zu einem TypeError, der den Stream abbricht; sonst wird sie durch U+FFFD (�) ersetzt.
$options.ignoreBOM boolean false Bei true bleibt eine Byte-Order-Mark im Ausgabetext erhalten; standardmäßig wird sie entfernt.

Rückgabewert

Typ
TextDecoderStream
Beschreibung
Ein neues TextDecoderStream-Objekt mit den Eigenschaften readable (ReadableStream<string>), writable (WritableStream<BufferSource>) sowie encoding, fatal und ignoreBOM.

Beispiele

Fetch-Antwort schrittweise als Text lesen

const streamText = async (url) => {
  const response = await fetch(url);
  const reader = response.body
    .pipeThrough(new TextDecoderStream())
    .getReader();

  let text = '';
  while (true) {
    const { value, done } = await reader.read();
    if (done) break;
    text += value;
    console.log('Chunk empfangen:', value.length, 'Zeichen');
  }
  return text;
};

streamText('/logs/app.log').then((t) => console.log('Gesamt:', t.length));
Chunk empfangen: 65536 Zeichen Chunk empfangen: 12040 Zeichen Gesamt: 77576

Mehrbyte-Zeichen über Chunk-Grenzen hinweg

// „ä“ ist in UTF-8 0xC3 0xA4 – wir teilen es absichtlich auf zwei Chunks
const source = new ReadableStream({
  start(controller) {
    controller.enqueue(new Uint8Array([0x48, 0xC3]));
    controller.enqueue(new Uint8Array([0xA4, 0x6C, 0x6C, 0x6F]));
    controller.close();
  }
});

const text = await new Response(
  source.pipeThrough(new TextDecoderStream())
).text();
console.log(text);
Hällo

Legacy-Kodierung mit strenger Fehlerprüfung (NDJSON)

const readNdjson = async (url) => {
  const decoder = new TextDecoderStream('windows-1252', { fatal: true });
  console.log(decoder.encoding); // normalisierter Name

  const reader = (await fetch(url)).body.pipeThrough(decoder).getReader();
  let buffer = '';
  const records = [];

  for (;;) {
    const { value, done } = await reader.read();
    if (value) buffer += value;
    const lines = buffer.split('\n');
    buffer = done ? '' : lines.pop();
    for (const line of lines) {
      if (line.trim()) records.push(JSON.parse(line));
    }
    if (done) break;
  }
  return records;
};

readNdjson('/export/daten.ndjson').then((r) => console.log(r.length, 'Datensätze'));
windows-1252 42 Datensätze

// Wichtig · Fallstricke

  • Chunk-Grenzen ≠ Zeilengrenzen: Der Stream setzt Zeichen korrekt zusammen, aber keine Zeilen oder JSON-Objekte. Zeilenweises Parsen muss man selbst puffern (siehe Beispiel 3).
  • Nur Binärdaten schreiben: Wer Strings in writable schreibt, erhält einen TypeError.
  • Ungültiges Label wirft sofort einen RangeError. Die Bezeichnung wird normalisiert: \"latin1\" wird z. B. zu \"windows-1252\".
  • fatal: true bricht den gesamten Stream ab – beim Lesen ist deshalb try/catch nötig.
  • Kompatibilität: In allen modernen Browsern verfügbar (Firefox erst ab 105), in Node.js global ab Version 18 (vorher über stream/web). Die Gegenrichtung TextEncoderStream unterstützt nur UTF-8.
  • Ein TextDecoderStream kann nur einmal durchlaufen werden; für jeden neuen Datenstrom eine neue Instanz erzeugen.