`DataView` ב-JavaScript
מאמר זה מסביר על DataView
ב-JavaScript.
נסביר בפירוט את השימוש הבסיסי ב-DataView
ודוגמאות ספציפיות לשימוש בו.
YouTube Video
DataView
ב-JavaScript
DataView
ב-JavaScript הוא API נוח למניפולציה של נתונים המאוחסנים במאגרים (ArrayBuffer
) בפורמטים שונים. זה מאפשר קריאה וכתיבה גמישים ויעילים של נתונים בינריים, ומשמש תפקיד חשוב בתקשורת רשת, בעיבוד קבצים ובאינטראקציה עם WebAssembly.
מהו DataView
?
DataView
מספק שכבת צפייה מעל עצם ArrayBuffer
, ומאפשר קריאה וכתיבה של סוגי נתונים שונים (כגון מספרים שלמים, מספרי נקודה צפה ותווים) מכל מיקום בתים. DataView
דומה ל-TypedArray
, אך הוא מתאפיין ביכולתו לציין סדר בתים (endianness) ולבצע פעולות מפורטות ברמת בתים.
תחביר בסיסי של DataView
1let buffer = new ArrayBuffer(16); // Create a 16-byte ArrayBuffer
2let view = new DataView(buffer); // Manipulate the buffer with a DataView
DataView
כולל בנאי (constructor) שמקבל ArrayBuffer
כטיעון. בדוגמה זו, נוצר מאגר בגודל 16 בתים, ו-DataView
משמש כדי לגשת למאגר זה. בשימוש ב-DataView
, ניתן לציין גדלים שונים של בתים וסדר בתים (big-endian או little-endian) כאשר קוראים או כותבים נתונים המאוחסנים במאגר.
שיטות בסיסיות של DataView
DataView
מספק שיטות לקריאה וכתיבה של ערכים מסוגי נתונים שונים. השיטות מחולקות בעיקר לשיטות get
עבור קריאה ולשיטות set
עבור כתיבה.
השיטות העיקריות מוצגות למטה.
שיטות לקריאת ערכים
getInt8(byteOffset)
: קורא מספר שלם (signed) בגודל בית בודד מהמיקום שצוין.getUint8(byteOffset)
: קורא מספר שלם (unsigned) בגודל בית בודד מהמיקום שצוין.getInt16(byteOffset, littleEndian)
: קורא מספר שלם (signed) בגודל 2 בתים.getUint16(byteOffset, littleEndian)
: קורא מספר שלם (unsigned) בגודל 2 בתים.getInt32(byteOffset, littleEndian)
: קורא מספר שלם (signed) בגודל 4 בתים.getUint32(byteOffset, littleEndian)
: קורא מספר שלם (unsigned) בגודל 4 בתים.getFloat32(byteOffset, littleEndian)
: קורא מספר נקודה צפה בגודל 4 בתים בפורמט IEEE 754.getFloat64(byteOffset, littleEndian)
: קורא מספר נקודה צפה בן 8 בתים בפורמט IEEE 754.
שיטות לכתיבת ערכים
setInt8(byteOffset, value)
: כותב מספר שלם בעל סימן בגודל 1 בית.setUint8(byteOffset, value)
: כותב מספר שלם ללא סימן בגודל 1 בית.setInt16(byteOffset, value, littleEndian)
: כותב מספר שלם בעל סימן בגודל 2 בתים.setUint16(byteOffset, value, littleEndian)
: כותב מספר שלם ללא סימן בגודל 2 בתים.setInt32(byteOffset, value, littleEndian)
: כותב מספר שלם בעל סימן בגודל 4 בתים.setUint32(byteOffset, value, littleEndian)
: כותב מספר שלם ללא סימן בגודל 4 בתים.setFloat32(byteOffset, value, littleEndian)
: כותב מספר נקודה צפה בן 4 בתים בפורמט IEEE 754.setFloat64(byteOffset, value, littleEndian)
: כותב מספר נקודה צפה בן 8 בתים בפורמט IEEE 754.
על ידי שימוש בשיטות הללו, ניתן לקרוא ולכתוב נתונים המאוחסנים בתוך ArrayBuffer
בצורה גמישה.
דוגמה לשימוש ב-DataView
בואו נסתכל על דוגמה של עיבוד נתונים בינאריים באמצעות DataView
.
דוגמה 1: כתיבה וקריאה של מספר שלם בן 16 סיביות
1let buffer = new ArrayBuffer(4); // Create a 4-byte buffer
2let view = new DataView(buffer);
3
4// Write a 2-byte integer value in little-endian format
5view.setInt16(0, 32767, true); // byteOffset: 0, value: 32767, littleEndian: true
6
7// Read the data in little-endian format
8let value = view.getInt16(0, true);
9console.log(value); // Output: 32767
- בדוגמה זו, נעשה שימוש בשיטת
setInt16
כדי לכתוב מספר שלם בעל סימן בן 16 סיביות בפורמט little-endian, ושיטתgetInt16
קוראת את הערך בפורמט זה.
דוגמה 2: כתיבה וקריאה של מספר נקודה צפה
1let buffer = new ArrayBuffer(8); // Create an 8-byte buffer
2let view = new DataView(buffer);
3
4// Write an 8-byte floating-point number
5view.setFloat64(0, 3.14159, false); // byteOffset: 0, value: 3.14159, bigEndian: false
6
7// Read the data in big-endian format
8let pi = view.getFloat64(0, false);
9console.log(pi); // Output: 3.14159
- בדוגמה זו, נעשה שימוש בשיטת
setFloat64
כדי לכתוב מספר נקודה צפה בן 64 סיביות בפורמט big-endian, והערך נקרא באמצעותgetFloat64
.
על אודות Endianness
בואו נראה דוגמה של קריאה וכתיבה של ערכים בפורמטים של big-endian ו-little-endian באמצעות DataView
.
1// Example: Handling Endianness with DataView in TypeScript
2// Create an ArrayBuffer of 4 bytes
3const buffer = new ArrayBuffer(4);
4const view = new DataView(buffer);
5
6// Store the same number (0x12345678) in both endian formats
7// By default, DataView uses big-endian
8view.setUint32(0, 0x12345678); // Big-endian
9console.log("Big-endian (default):");
10console.log(buffer);
11
12// Overwrite the buffer with little-endian
13view.setUint32(0, 0x12345678, true); // Little-endian
14console.log("Little-endian:");
15console.log(buffer);
16
17// Read values back in both endian modes
18const bigEndianValue = view.getUint32(0); // Big-endian read
19const littleEndianValue = view.getUint32(0, true); // Little-endian read
20
21console.log("Read as Big-endian:", bigEndianValue.toString(16));
22console.log("Read as Little-endian:", littleEndianValue.toString(16));
בשיטות DataView
, נתונים מאוחסנים כברירת מחדל בפורמט big-endian (סדר בתים מהבית החשוב ביותר לפחות חשוב), אך ניתן לציין גם את הפורמט little-endian באופן אופציונלי. פורמט little-endian הופך את סדר הבתים (מהבית הפחות חשוב אל החשוב ביותר). חשוב לטפל בסדר הביתים (Endianness) של נתונים בצורה נכונה, כיוון שמערכות ופרוטוקולי רשת שונים משתמשים בסדרי ביתים שונים.
הבדל מ-TypedArray
בואו נסתכל על ההבדלים בין DataView
ל-TypedArray
.
1// Example: TypedArray vs DataView
2
3// Create a 8-byte buffer
4const buffer = new ArrayBuffer(8);
5
6// --- Using TypedArray (Int32Array) ---
7const int32View = new Int32Array(buffer);
8int32View[0] = 42;
9int32View[1] = 100;
10
11console.log("TypedArray (Int32Array):");
12console.log(int32View); // Int32Array [42, 100]
13
14// --- Using DataView ---
15const dataView = new DataView(buffer);
16
17// Write different types of data at arbitrary byte offsets
18dataView.setInt8(0, 65); // 1 byte
19dataView.setUint16(1, 500, true); // 2 bytes, little-endian
20dataView.setFloat32(3, 3.14, true); // 4 bytes, little-endian
21
22console.log("\nDataView:");
23console.log("Int8 at 0:", dataView.getInt8(0)); // 65
24console.log("Uint16 at 1:", dataView.getUint16(1, true)); // 500
25console.log("Float32 at 3:", dataView.getFloat32(3, true)); // 3.14
26
27/*
28Output:
29TypedArray (Int32Array):
30Int32Array [42, 100]
31
32DataView:
33Int8 at 0: 65
34Uint16 at 1: 500
35Float32 at 3: 3.140000104904175
36*/
TypedArray
גם היא מספקת פעולות על buffers המבוססים על ArrayBuffer
, אך היא מתאימה במיוחד לעיבוד נתונים רציפים עם אורך ופורמט קבועים לכל סוג נתון. לעומת זאת, DataView
מאפשרת פעולה גמישה על סוגי נתונים שונים וגם מאפשרת שליטה על פורמט ה-endianness. לכן, DataView
מתאימה לניתוח ובנייה של נתונים בינאריים מורכבים.
סיכום
DataView
הוא API חזק לעבודה עם נתונים בינריים ב-JavaScript. ניתן לגשת ישירות ל-ArrayBuffer
כדי לקרוא ולכתוב נתונים תוך התחשבות במספרים שלמים, מספרים בנקודה צפה והבדלים ב-endianness. זה שימושי במצבים כמו תקשורת ברשת וניתוח פורמטי קבצים, והוא חיוני במקרים שבהם נדרשת שליטה ברמת הבייט. על ידי שימוש ב-DataView יחד עם TypedArray
, ניתן לבצע עיבוד נתונים בינאריים בצורה יעילה יותר.
תוכלו לעקוב אחר המאמר שלמעלה באמצעות Visual Studio Code בערוץ היוטיוב שלנו. נא לבדוק גם את ערוץ היוטיוב.