Start · Sprachen · JavaScript · Referenz · TextEncoder

TextEncoder

Schnittstelle

Kodiert JavaScript-Strings als UTF-8-Bytes und liefert sie als <code>Uint8Array</code>. Andere Zeichenkodierungen werden nicht unterstützt.

seit JavaScript Baseline: alle Browser (seit 2020 vollständig), No Kategorie: webapi

Signatur

interface TextEncoder

Beschreibung

Mit TextEncoder wandelt man einen JavaScript-String, der intern als UTF-16 vorliegt, in eine Folge von UTF-8-Bytes um. Das Ergebnis ist ein Uint8Array. Man braucht das überall dort, wo Binärdaten statt Text erwartet werden: bei der Web Crypto API (crypto.subtle.digest, sign, encrypt), bei WebSockets und WebRTC-Datenkanälen mit Binärübertragung, bei Streams, WebAssembly-Speicher, Blob-Inhalten oder wenn man die tatsächliche Bytelänge eines Strings ermitteln will.

Die Schnittstelle ist bewusst schlicht gehalten. Der Konstruktor new TextEncoder() nimmt keine Parameter entgegen, denn die Kodierung ist fest UTF-8. Die schreibgeschützte Eigenschaft encoding liefert immer "utf-8". Es gibt zwei Methoden:

  • encode(string) gibt ein neues Uint8Array mit den kodierten Bytes zurück.
  • encodeInto(string, uint8Array) schreibt die Bytes in einen bereits vorhandenen Puffer und gibt ein Objekt { read, written } zurück. Es erzeugt dabei kein neues Array und eignet sich deshalb für leistungskritischen Code, etwa beim Schreiben in WebAssembly-Speicher.

Die Gegenrichtung, also Bytes zurück in einen String, übernimmt TextDecoder. Für kontinuierliche Datenströme gibt es TextEncoderStream, das sich in eine pipeThrough()-Kette einfügen lässt.

Parameter

Name Typ Default Beschreibung
$string string "" Parameter von encode() und encodeInto(): der zu kodierende Text. Andere Werte als Strings werden mit String() umgewandelt.
$uint8Array Pflicht Uint8Array Nur bei encodeInto(): der Zielpuffer, in den die UTF-8-Bytes geschrieben werden.

Beispiele

Instanz erzeugen und String kodieren

const encoder = new TextEncoder();
console.log(encoder.encoding);

const bytes = encoder.encode('Grüße €');
console.log(bytes);
console.log(`${'Grüße €'.length} Zeichen, ${bytes.length} Bytes`);
utf-8 Uint8Array(11) [71, 114, 195, 188, 195, 159, 101, 32, 226, 130, 172] 7 Zeichen, 11 Bytes

SHA-256-Hash eines Strings mit der Web Crypto API

const sha256 = async (text) => {
  const data = new TextEncoder().encode(text);
  const hashBuffer = await crypto.subtle.digest('SHA-256', data);
  return [...new Uint8Array(hashBuffer)]
    .map((b) => b.toString(16).padStart(2, '0'))
    .join('');
};

console.log(await sha256('hallo'));
d3751d33f9cd5049c4af2b462735457e4d3baf130bcbb87f389e349fbaeb20b9

encodeInto() mit vorab reserviertem Puffer

const encoder = new TextEncoder();
const buffer = new Uint8Array(8);

const { read, written } = encoder.encodeInto('Öl & Äpfel', buffer);
console.log(read, written);
console.log(new TextDecoder().decode(buffer.subarray(0, written)));
6 8 Öl & Ä

Bytelänge prüfen, bevor gesendet wird

const MAX_BYTES = 16;
const encoder = new TextEncoder();

const passtInLimit = (text) => encoder.encode(text).byteLength <= MAX_BYTES;

console.log(passtInLimit('Hallo Welt'));
console.log(passtInLimit('😀😀😀😀😀'));
true false

// Wichtig · Fallstricke

  • Nur UTF-8: Anders als in alten Entwürfen der Spezifikation akzeptiert der Konstruktor kein Kodierungs-Argument mehr, ein übergebenes Argument wird einfach ignoriert. Für ISO-8859-1, UTF-16 und ähnliche Kodierungen braucht man eine eigene Umsetzung oder eine Bibliothek. TextDecoder kann dagegen viele Kodierungen lesen.
  • Zeichenzahl und Bytezahl unterscheiden sich: string.length zählt UTF-16-Codeeinheiten, nicht Bytes. Umlaute belegen in UTF-8 2 Bytes, das €-Zeichen 3 und Emojis 4. Wenn Speicher- oder Protokollgrenzen einzuhalten sind, sollte man immer encode(text).byteLength messen.
  • Einzelne Surrogate: Ungültige, einzeln stehende UTF-16-Surrogate werden stillschweigend durch U+FFFD (EF BF BD) ersetzt. Ein Hin- und Rückweg über Kodieren und Dekodieren gibt solche Strings deshalb nicht verlustfrei wieder.
  • Puffergröße bei encodeInto(): Ist der Puffer zu klein, wird still abgeschnitten, und zwar nur an Zeichengrenzen. Anhand von read und written muss man selbst prüfen, ob alles hineingepasst hat. Ein Puffer mit text.length * 3 Bytes reicht garantiert aus.
  • Wiederverwenden: Eine Instanz hat keinen Zustand und kann beliebig oft benutzt werden. In Schleifen sollte man sie also nicht jedes Mal neu anlegen.
  • Kompatibilität: Alle modernen Browser unterstützen die Schnittstelle, auch in Web Workern. In Node.js ist sie ab Version 11 global verfügbar, davor über require('util').TextEncoder. encodeInto() kam später hinzu (Chrome 74, Firefox 66, Safari 14.1). Internet Explorer unterstützt die Schnittstelle nicht.