TypedArray in TypeScript
Dieser Artikel erklärt TypedArray in TypeScript.
Wir erklären TypedArray in TypeScript, einschließlich praktischer Beispiele.
YouTube Video
TypedArray in TypeScript
TypedArray ist ein Mechanismus zur effizienten Verarbeitung von Binärdaten. Es ist besonders nützlich für Low-Level-Binäroperationen wie große Bilddaten, Netzwerk-Bytestreams und numerische Arrays für WebGL.
So erstellt man einen ArrayBuffer
ArrayBuffer repräsentiert einen Bereich von Bytes mit fester Länge. Erstellen Sie zunächst einen Buffer und überprüfen Sie dessen Größe und Byte-Länge.
1// Create an ArrayBuffer of 16 bytes
2const buffer: ArrayBuffer = new ArrayBuffer(16);
3console.log("buffer.byteLength:", buffer.byteLength); // 16
- Dieser Code erstellt einen leeren Bereich mit 16 Bytes.
ArrayBufferselbst verfügt nicht über Lese-/Schreibfunktionen; der Zugriff erfolgt daher überTypedArrayoderDataView.
Typen von TypedArray
Es gibt viele Arten von TypedArray, beispielsweise die folgenden. Diese unterscheiden sich je nach Datentyp und der Größe, die sie verarbeiten können.
| TypedArray | Datentyp | Bitgröße |
|---|---|---|
Int8Array |
8-Bit-Ganzzahl | 8 Bits |
Uint8Array |
Unsigned 8-Bit-Ganzzahl | 8 Bits |
Uint8ClampedArray |
Abgegrenzte unsigned 8-Bit-Ganzzahl | 8 Bits |
Int16Array |
16-Bit-Ganzzahl | 16 Bits |
Uint16Array |
Unsigned 16-Bit-Ganzzahl | 16 Bits |
Int32Array |
32-Bit-Ganzzahl | 32 Bits |
Uint32Array |
Unsigned 32-Bit-Ganzzahl | 32 Bits |
Float32Array |
32-Bit-Gleitkommazahl | 32 Bit |
Float64Array |
64-Bit-Gleitkommazahl | 64 Bit |
Grundlegende TypedArrays (Uint8Array, Int16Array, Float32Array usw.)
TypedArray erzeugt eine 'typisierte Ansicht' auf einem ArrayBuffer. Nachfolgend finden Sie Beispiele zum Erstellen und Verwenden typischer TypedArrays.
1// Create a buffer and different typed views over it
2const buf = new ArrayBuffer(8); // 8 bytes
3
4// Create views
5const u8 = new Uint8Array(buf); // 8 x uint8
6const i16 = new Int16Array(buf); // 4 x int16 (since each int16 is 2 bytes)
7const f32 = new Float32Array(buf); // 2 x float32 (4 bytes each)
8
9console.log("Uint8 length:", u8.length);
10console.log("Int16 length:", i16.length);
11console.log("Float32 length:", f32.length);- Durch die Erstellung mehrerer Ansichten auf demselben
ArrayBufferkönnen Sie denselben Speicher in unterschiedlichen Typen oder Granularitäten lesen und schreiben.lengthder Ansicht ist die Anzahl der Elemente,byteLengthdie Anzahl der Bytes.
Schreiben und Lesen (Operationen auf Byte-Ebene)
Beim Schreiben eines Wertes in ein TypedArray werden die entsprechenden Bytes im Speicher aktualisiert. Sie können die Änderungen sehen, wenn Sie denselben Buffer mit einer anderen Ansicht einlesen.
1// Demonstrate writing via one view and reading via another
2const buffer2 = new ArrayBuffer(4);
3const u8view = new Uint8Array(buffer2);
4const u32view = new Uint32Array(buffer2);
5
6u8view[0] = 0x78;
7u8view[1] = 0x56;
8u8view[2] = 0x34;
9u8view[3] = 0x12;
10
11console.log("Uint8 bytes:", Array.from(u8view)); // [120, 86, 52, 18]
12console.log("Uint32 value (platform endianness):", u32view[0]); // value depends on endianness
- In diesem Beispiel schreiben wir eine Bytesequenz und lesen denselben Bereich anschließend als 32-Bit-Integer ein. Beachten Sie, dass die Ausgabe von der Endianess der Ausführungsumgebung abhängt.
Endianness (Byte-Reihenfolge) und DataView
DataView ist praktisch, wenn Sie umgebungsabhängige Endianness-Probleme kontrollieren möchten. DataView ermöglicht es Ihnen, die Endianness beim Lesen und Schreiben anzugeben.
1// Use DataView to read/write with explicit endianness control
2const b = new ArrayBuffer(4);
3const dv = new DataView(b);
4
5// write little-endian 32-bit integer
6dv.setUint32(0, 0x12345678, true);
7
8// read as little-endian and big-endian
9const little = dv.getUint32(0, true);
10const big = dv.getUint32(0, false);
11
12console.log("little-endian read:", little.toString(16)); // "12345678"
13console.log("big-endian read:", big.toString(16)); // different value
DataViewist ein praktischer Mechanismus, um Bytes im Detail zu lesen und zu schreiben. Es unterstützt verschiedene Typen wie signierte/unsignierte Ganzzahlen und Gleitkommazahlen. Außerdem können Sie explizit die Endianness (Byte-Reihenfolge) angeben, was beim Implementieren von Binärprotokollen sehr hilfreich ist.
Unterschied zwischen subarray und slice
subarray eines TypedArray gibt eine Ansicht zurück, die den Original-Buffer teilt, während slice eine neue Kopie liefert. Performance und Seiteneffekte unterscheiden sich je nach verwendeter Methode.
1const base = new Uint8Array([1, 2, 3, 4, 5]);
2
3const shared = base.subarray(1, 4); // shares underlying buffer
4const copied = base.slice(1, 4); // copies data
5
6shared[0] = 99;
7console.log("base after shared modification:", base); // shows change
8console.log("copied remains:", copied); // unaffected
- Wenn Sie die geteilte Ansicht ändern, wird auch das ursprüngliche Array geändert, was unbeabsichtigte Nebenwirkungen verursachen kann. Wenn Sie das ursprüngliche Array sicher erhalten möchten, können Sie im Voraus eine Kopie mit
slice()erstellen.
Kopieren von Buffern und Typumwandlung (Konvertierung zwischen TypedArrays)
Wir erklären, wie Sie Daten zwischen TypedArrays kopieren und Teile mit der set-Methode einfügen.
1// Copy and convert between typed arrays
2const src = new Float32Array([1.5, 2.5, 3.5]);
3const dst = new Uint16Array(src.length);
4
5// Convert by mapping (explicit conversion)
6for (let i = 0; i < src.length; i++) {
7 dst[i] = Math.round(src[i]); // simple conversion rule
8}
9console.log("converted dst:", Array.from(dst)); // [2, 2, 4]
10
11// Using set to copy bytes (requires compatible underlying buffer or same element type)
12const src2 = new Uint8Array([10, 20, 30]);
13const dst2 = new Uint8Array(6);
14dst2.set(src2, 2); // copy src2 into dst2 starting at index 2
15console.log("dst2 after set:", Array.from(dst2)); // [0,0,10,20,30,0]
- Unterscheiden sich die Elementtypen, müssen Sie Werte umwandeln, z. B. durch Runden oder Bereichsprüfung, statt sie einfach zu kopieren.
setermöglicht ein schnelles Kopieren zwischenTypedArrays mit dem gleichen Elementtyp.
Praktisches Beispiel: Ein Parser für ein Binärprotokoll (einfache Implementierung)
Hier zeigen wir ein einfaches Parser-Beispiel, das Binärdaten mit festem Format liest: Einem 1-Byte-Typ, einer 2-Byte-Datenlänge und anschließendem Payload.
1// Simple binary message parser:
2// format: [type: uint8][length: uint16 BE][payload: length bytes]
3function parseMessages(buffer: ArrayBuffer) {
4 const dv = new DataView(buffer);
5 let offset = 0;
6 const messages: { type: number; payload: Uint8Array }[] = [];
7
8 while (offset + 3 <= dv.byteLength) {
9 const type = dv.getUint8(offset);
10 const length = dv.getUint16(offset + 1, false); // big-endian
11 offset += 3;
12 if (offset + length > dv.byteLength) break; // truncated
13 const payload = new Uint8Array(buffer, offset, length);
14 messages.push({ type, payload });
15 offset += length;
16 }
17
18 return messages;
19}
20
21// Example usage
22const buf = new ArrayBuffer(1 + 2 + 3 + 1 + 2 + 2); // two messages
23const dv = new DataView(buf);
24let off = 0;
25// first message: type=1, length=3, payload=[1,2,3]
26dv.setUint8(off, 1); dv.setUint16(off + 1, 3, false); off += 3;
27new Uint8Array(buf, off, 3).set([1, 2, 3]); off += 3;
28// second message: type=2, length=2, payload=[9,8]
29dv.setUint8(off, 2); dv.setUint16(off + 1, 2, false); off += 3;
30new Uint8Array(buf, off, 2).set([9, 8]);
31
32console.log(parseMessages(buf));- In diesem Beispiel wird der Header mit
DataViewausgelesen und der Payload-Ausschnitt mitUint8Arrayerstellt. Endianness und Prüfung der Buffer-Länge sind wichtig.
Web-API und TypedArray (Beispiel: Binärdaten abrufen)
Dies ist ein typisches Beispiel für die Behandlung eines von einer Netzwerk-Anfrage erhaltenen ArrayBuffer mittels TypedArray.
1// Example of fetching binary and mapping to typed array
2async function fetchBinary(url: string) {
3 const res = await fetch(url);
4 const ab = await res.arrayBuffer();
5 const view = new Uint8Array(ab);
6 // process view...
7 console.log("received bytes:", view.length);
8 return view;
9}
10
11// Usage (call in async context)
12// fetchBinary("/path/to/file.bin");
- Sie können den mit
Response.arrayBuffer()erhaltenenArrayBufferdirekt an einTypedArrayübergeben. Es wird für Bilder, Audio oder benutzerdefinierte Binärprotokolle verwendet.
Performance-Tipps und häufige Fallstricke
Hier sind einige 'Performance-Tipps' und 'häufige Fallstricke', die beim Einsatz von TypedArrays hilfreich sind:.
-
Vermeiden Sie unnötiges Kopieren Um große Daten effizient zu verarbeiten, können Sie unnötiges Kopieren vermeiden, indem Sie Teilansichten mit
subarrayerstellen oder denselbenArrayBufferfür mehrere Views nutzen. -
Seien Sie vorsichtig bei der Endianness Bei Netzwerkkommunikation oder Dateiformaten ist die Reihenfolge der Daten (Byte-Order) oft vorgegeben. Mit
DataViewkönnen Sie die Endianness beim Lesen und Schreiben explizit angeben und so Fehlinterpretationen vermeiden. -
Beachten Sie die Wertebereiche der einzelnen Typen Zum Beispiel kann
Uint8nur Werte von 0 bis 255 darstellen. Wenn Sie einen negativen Wert eingeben, kann es zu einer Abschneidung oder einem Überlauf kommen, daher sollten Sie bei Bedarf Umwandlungsregeln definieren. -
Berücksichtigen Sie die Belastung für die Speicherbereinigung (Garbage Collection) Das häufige Neuerstellen großer
ArrayBuffererhöht die Belastung des Speichermanagements. In performancekritischen Situationen sollten Sie den Code so gestalten, dass vorhandene Puffer möglichst wiederverwendet werden.
Zusammenfassung
TypedArray ist ein Mechanismus, um Binärdaten schnell und effizient zu verarbeiten. Durch die Kombination von ArrayBuffer, der einen Bereich mit fester Byte-Länge reserviert, und TypedArray bzw. DataView, die Inhalte in bestimmten Typen lesen und schreiben, können Sie flexible Binäroperationen durchführen. Je nach Anwendungsfall können Sie zwischen der Verwendung von subarray/slice oder DataView wählen und Ihre Implementierung unter Berücksichtigung von Endianess und Kopien gestalten.
Sie können den obigen Artikel mit Visual Studio Code auf unserem YouTube-Kanal verfolgen. Bitte schauen Sie sich auch den YouTube-Kanal an.