TypedArray i TypeScript
Den här artikeln förklarar TypedArray i TypeScript.
Vi kommer att förklara TypedArray i TypeScript, inklusive praktiska exempel.
YouTube Video
TypedArray i TypeScript
TypedArray är en mekanism för att effektivt hantera binärdata. Det är särskilt användbart för lågnivå-binära operationer som stora bilddata, nätverksbyte-strömmar och numeriska arrayer för WebGL.
Hur man skapar en ArrayBuffer
ArrayBuffer representerar ett område av bytes med fast längd. Skapa först en buffert och kontrollera dess storlek och byte-längd.
1// Create an ArrayBuffer of 16 bytes
2const buffer: ArrayBuffer = new ArrayBuffer(16);
3console.log("buffer.byteLength:", buffer.byteLength); // 16
- Denna kod skapar ett tomt område på 16 byte.
ArrayBufferhar ingen egen läs-/skriv-funktion, så du får tillgång till den viaTypedArrayellerDataView.
Typer av TypedArray
Det finns många typer av TypedArray, till exempel följande. Dessa varierar beroende på vilken datatyp och storlek de hanterar.
| TypedArray | Datatyp | Bitar |
|---|---|---|
Int8Array |
8-bitars heltal | 8 bitar |
Uint8Array |
Osignerat 8-bitars heltal | 8 bitar |
Uint8ClampedArray |
Begränsat osignerat 8-bitars heltal | 8 bitar |
Int16Array |
16-bitars heltal | 16 bitar |
Uint16Array |
Osignerat 16-bitars heltal | 16 bitar |
Int32Array |
32-bitars heltal | 32 bitar |
Uint32Array |
Osignerat 32-bitars heltal | 32 bitar |
Float32Array |
32-bitars flyttal | 32 bitar |
Float64Array |
64-bitars flyttal | 64 bitar |
Grundläggande TypedArray-typer (Uint8Array, Int16Array, Float32Array, osv.)
TypedArray skapar en 'typad vy' ovanpå en ArrayBuffer. Nedan följer exempel på hur man skapar och använder några vanliga TypedArray-typer.
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);- Genom att skapa flera vyer på samma
ArrayBufferkan du läsa och skriva samma minne med olika typer eller detaljnivåer.lengthför vyn är antal element, medanbyteLengthär antal byte.
Skriva och läsa (operationer på byte-nivå)
När du skriver ett värde till en TypedArray uppdateras motsvarande byte i minnet. Du kan se ändringarna om du läser samma buffert med en annan vy.
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
- I detta exempel skriver vi en bytesekvens och läser sedan samma område som ett 32-bitars heltal. Observera att utdata beror på slutmiljöns endianness (byteordning).
Endianness (byteordning) och DataView
DataView är användbart om du vill hantera miljöberoende endianness-problem. DataView låter dig ange byteordning när du läser och skriver.
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
DataViewär en bekväm mekanism för detaljerad läsning och skrivning av byte. Den stöder olika typer, som heltal med och utan tecken samt flyttal, och låter dig uttryckligen ange byteordning (endianness), vilket är mycket användbart när du implementerar binära protokoll.
Skillnad mellan subarray och slice
subarray på en TypedArray returnerar en vy som delar originalbufferten, medan slice returnerar en ny kopia. Prestanda och bieffekter skiljer sig beroende på vilken du använder.
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
- Om du ändrar den delade vyn kommer den ursprungliga arrayen också att ändras, vilket kan orsaka oavsiktliga bieffekter. Om du vill bevara den ursprungliga arrayen säkert kan du skapa en kopia i förväg med hjälp av
slice().
Kopiering av buffertar och typomvandling (omvandling mellan olika TypedArray-typer)
Vi förklarar hur du kopierar data mellan TypedArray-typer och hur du klistrar in delar med hjälp av set-metoden.
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]
- Om elementtyperna skiljer sig behöver du konvertera värdena, t.ex. genom avrundning eller granskning av intervall, istället för att bara kopiera.
setmöjliggör snabb kopiering mellanTypedArray-typer av samma elementtyp.
Praktiskt exempel: En binär protokoll-parser (enkel implementation)
Här presenterar vi ett enkelt parser-exempel som läser binärdata i fast format bestående av en 1-byte-typ, 2-byte datalängd och efterföljande 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));- I det här exemplet läses headern med
DataView, och biten med användardata (payload) skapas medUint8Array. Endianness och kontroll av buffertlängd är viktigt.
Webb-API och TypedArray (exempel: hämta binärdata)
Detta är ett typiskt exempel på hur man hanterar en ArrayBuffer som erhållits från ett nätverksanrop med hjälp av 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");
- Du kan direkt skicka den
ArrayBufferdu hämtat viaResponse.arrayBuffer()till enTypedArray. Det används för bilder, ljud eller egna binära protokoll.
Prestandatips och vanliga fallgropar
Här följer några 'prestandatips' och 'vanliga fallgropar' som är bra att känna till när du använder TypedArray-typer:.
-
Undvik onödig kopiering För att bearbeta stora datamängder effektivt kan du minska onödig kopiering genom att skapa delvisa vyer med
subarrayeller dela sammaArrayBuffermellan flera vyer. -
Var uppmärksam på endianness (byteordning) För nätverkskommunikation eller filformat anges ofta ordningen på datan (byteordning). Med
DataViewkan du ange byteordning explicit vid läsning och skrivning, vilket förhindrar oavsiktliga misstolkningar. -
Var medveten om värdeintervall för varje typ Till exempel kan
Uint8bara representera värden mellan 0 och 255. Om du anger ett negativt värde kan trunkering eller överrullning av värden uppstå, så du bör definiera konverteringsregler efter behov. -
Tänk på belastning för garbage collection Att ofta återskapa stora
ArrayBuffer-objekt ökar belastningen på minneshanteringen. I prestandakritiska situationer kan du överväga att utforma koden så att befintliga buffertar återanvänds så mycket som möjligt.
Sammanfattning
TypedArray är en mekanism för att hantera binärdata snabbt och effektivt. Genom att kombinera ArrayBuffer, som reserverar ett område av bytes med fast längd, med TypedArray eller DataView, som läser och skriver innehållet med specifika typer, kan du utföra flexibla binära operationer. Beroende på användningsfallet kan du välja mellan att använda subarray/slice eller DataView och utforma din implementation med hänsyn till ändianhet och kopior.
Du kan följa med i artikeln ovan med hjälp av Visual Studio Code på vår YouTube-kanal. Vänligen kolla även in YouTube-kanalen.