TypedArray i TypeScript
Denne artikel forklarer TypedArray i TypeScript.
Vi vil forklare TypedArray i TypeScript, inklusive praktiske eksempler.
YouTube Video
TypedArray i TypeScript
TypedArray er en mekanisme til effektiv håndtering af binære data. Det er især nyttigt til lav-niveau binære operationer såsom store billeddata, netværksbyte-strømme og numeriske arrays til WebGL.
Sådan opretter du en ArrayBuffer
ArrayBuffer repræsenterer et område af bytes med fast længde. Først opretter du en buffer og tjekker dens størrelse og bytelængde.
1// Create an ArrayBuffer of 16 bytes
2const buffer: ArrayBuffer = new ArrayBuffer(16);
3console.log("buffer.byteLength:", buffer.byteLength); // 16
- Denne kode opretter et tomt område på 16 byte.
ArrayBufferhar ikke i sig selv læse-/skrivefunktioner, så du tilgår den gennemTypedArrayellerDataView.
Typer af TypedArray
Der findes mange typer af TypedArray, såsom følgende. Disse varierer afhængigt af den datatype og størrelse, de håndterer.
| TypedArray | Datatype | Bitlængde |
|---|---|---|
Int8Array |
8-bit heltal | 8 bits |
Uint8Array |
Usigneret 8-bit heltal | 8 bits |
Uint8ClampedArray |
Begrænset usigneret 8-bit heltal | 8 bits |
Int16Array |
16-bit heltal | 16 bits |
Uint16Array |
Usigneret 16-bit heltal | 16 bits |
Int32Array |
32-bit heltal | 32 bits |
Uint32Array |
Usigneret 32-bit heltal | 32 bits |
Float32Array |
32-bit flydende-kommat tal | 32 bits |
Float64Array |
64-bit flydende-kommat tal | 64 bits |
Basale TypedArrays (Uint8Array, Int16Array, Float32Array osv.)
TypedArray opretter et 'typed view' oven på en ArrayBuffer. Nedenfor er eksempler på oprettelse og brug af nogle typiske 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);- Ved at oprette flere views på den samme
ArrayBufferkan du læse og skrive den samme hukommelse i forskellige typer eller granulariteter.lengthaf viewet er antallet af elementer, ogbyteLengther antallet af bytes.
Skrivning og læsning (byte-niveau operationer)
Når du skriver en værdi til en TypedArray, opdateres de tilsvarende bytes i hukommelsen. Du kan se ændringerne, når du læser den samme buffer med et andet view.
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 dette eksempel skriver vi en bytesekvens og læser derefter det samme område som et 32-bit heltal. Bemærk, at output afhænger af endianness i eksekveringsmiljøet.
Endianness (byte-orden) og DataView
DataView er nyttigt, hvis du vil kontrollere miljøafhængige endianness-problemer. DataView giver dig mulighed for at angive endianness ved læsning og skrivning.
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
DataViewer en praktisk mekanisme til detaljeret læsning og skrivning af bytes. Den understøtter en række typer såsom signed/unsigned heltal og flydende tal, og giver dig mulighed for eksplicit at angive endianness (byte-orden), hvilket er meget nyttigt ved implementering af binære protokoller.
Forskel mellem subarray og slice
subarray på en TypedArray returnerer et view, der deler den originale buffer, mens slice returnerer en ny kopi. Ydelse og bivirkninger varierer afhængigt af, hvilken du bruger.
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
- Hvis du ændrer den delte visning, vil den oprindelige array også ændre sig, hvilket kan forårsage utilsigtede bivirkninger. Hvis du ønsker at bevare den oprindelige array sikkert, kan du på forhånd oprette en kopi ved hjælp af
slice().
Kopiering af buffers og typekonvertering (konvertering mellem TypedArrays)
Vi forklarer, hvordan man kopierer data mellem TypedArrays og indsætter dele med 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]
- Hvis elementtyperne er forskellige, skal du konvertere værdierne (f.eks. afrunding eller kontrol af værdier), i stedet for bare at kopiere.
settillader hurtig kopiering mellemTypedArrays af samme elementtype.
Praktisk eksempel: En parser til binær protokol (simpel implementering)
Her introducerer vi et simpelt parser-eksempel, der læser binære data i fast format bestående af 1 byte type, 2 byte datalængde og en efterfølgende 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 dette eksempel læses headeren med
DataView, og nyttelast-segmentet oprettes medUint8Array. Endianness og tjek af buffer-længde er vigtigt.
Web API og TypedArray (Eksempel: hentning af binære data)
Dette er et typisk eksempel på håndtering af en ArrayBuffer hentet fra et netværkskald ved hjælp af 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 direkte give en
ArrayBufferhentet medResponse.arrayBuffer()til enTypedArray. Den bruges til billeder, lyd eller brugerdefinerede binære protokoller.
Ydelsestips og almindelige faldgruber
Her er nogle 'ydelsestips' og 'almindelige faldgruber', som er nyttige at kende, når du bruger TypedArrays:.
-
Undgå unødig kopiering For at behandle store datamængder effektivt kan du mindske unødvendig kopiering ved at oprette delvise views med
subarrayeller dele den sammeArrayBufferi flere views. -
Vær opmærksom på endianness For netværkskommunikation eller filformater er rækkefølgen af data (byte-orden) ofte specificeret. Ved at bruge
DataViewkan du eksplicit angive endianness ved læsning og skrivning og undgå utilsigtet fejlfortolkning. -
Vær opmærksom på værdigrænser for hver type For eksempel kan
Uint8kun repræsentere værdier fra 0 til 255. Hvis du indtaster en negativ værdi, kan afkortning eller overløb forekomme, så du bør definere konverteringsregler efter behov. -
Tag hensyn til belastning af garbage collection Ofte at genskabe store
ArrayBuffers øger byrden for hukommelsesstyring. I præstationskritiske situationer kan du overveje at designe koden, så eksisterende buffere genbruges så meget som muligt.
Sammendrag
TypedArray er en mekanisme til hurtig og effektiv håndtering af binære data. Ved at kombinere ArrayBuffer, der reserverer et byteområde med fast længde, med TypedArray eller DataView, som læser og skriver indholdet med specifikke typer, kan du udføre fleksible binære operationer. Afhængig af dine anvendelsestilfælde kan du vælge mellem at bruge subarray/slice eller DataView og designe din implementering med opmærksomhed på endianness og kopier.
Du kan følge med i ovenstående artikel ved hjælp af Visual Studio Code på vores YouTube-kanal. Husk også at tjekke YouTube-kanalen.