دادههای دودویی (Binary Data)
ArrayBuffer و SharedArrayBuffer، TypedArray انواع آن، DataView، Blob و File و FileReader، TextEncoder و TextDecoder و کار با داده باینری.
داده دودویی چیست؟
رشتهها برای متن هستند اما برای فایل، تصویر، صدا و شبکه به بایتهای خام نیاز داریم:
رشته: "سلام" ← کاراکترها
دودویی: 0xD8 0xA9 0xD9... ← بایتها
// جاوا اسکریپت ساختارهای باینری:
ArrayBuffer → حافظه خام
TypedArray → دید عددی روی آن
DataView → خواندن/نوشتن کنترلشده
Blob/File → داده فایلمانند
ArrayBuffer — بافر خام
// ساخت بافر ۱۶ بایتی:
const buffer = new ArrayBuffer(16);
console.log(buffer.byteLength); // 16
// مستقیم قابل دسترسی نیست — نیاز به View:
const view = new Uint8Array(buffer);
view[0] = 255;
view[1] = 0x80; // هگزادسیمال
console.log(view[0]); // 255
console.log(view[1]); // 128
ArrayBuffer فقط حافظه است — بدون متد، بدون نوع. با TypedArray یا DataView آن را میخوانیم.
TypedArray — آرایه نوعدار
// انواع بر اساس اندازه و علامت:
// Int8 — ۱ بایت علامتدار (-128 تا 127)
// Uint8 — ۱ بایت بدون علامت (0 تا 255)
// Int16 — ۲ بایت (-32768 تا 32767)
// Uint16 — ۲ بایت (0 تا 65535)
// Int32 — ۴ بایت
// Uint32 — ۴ بایت
// Float32 — ۴ بایت اعشاری
// Float64 — ۸ بایت
// BigInt64 — ۸ بایت BigInt
// ساخت مستقیم:
const bytes = new Uint8Array([10, 20, 30]);
console.log(bytes.length); // 3
console.log(bytes[0]); // 10
// سرریز — مقدار wrap میشود:
bytes[0] = 300; // بیش از 255!
console.log(bytes[0]); // 44 — 300 % 256
// Int8 با علامت:
const signed = new Int8Array([127, -128]);
signed[0] = 128; // بیش از حد!
console.log(signed[0]); // -128
پیمایش و متدهای TypedArray
const data = new Uint8Array([5, 10, 15, 20, 25]);
// مثل آرایه:
console.log(data.length); // 5
console.log(data.indexOf(15)); // 2
data.forEach(v => console.log(v));
const doubled = data.map(v => v * 2);
console.log(doubled); // [10, 20, 30, 40, 50]
const filtered = data.filter(v => v > 10);
console.log(filtered); // [15, 20, 25]
const sum = data.reduce((a, b) => a + b, 0);
console.log(sum); // 75
// subarray — view بدون کپی:
const part = data.subarray(1, 3);
console.log(part); // [10, 15] — همان حافظه!
// copy — کپی واقعی:
const copy = data.slice(1, 3);
console.log(copy); // [10, 15] — جدید
// set — جایگذاری:
const target = new Uint8Array(5);
target.set([1, 2, 3], 1); // از ایندکس 1
console.log(target); // [0, 1, 2, 3, 0]
DataView — خواندن دقیق
const buffer = new ArrayBuffer(8);
const view = new DataView(buffer);
// نوشتن در offset مشخص:
view.setInt16(0, 12345); // ۲ بایت در ابتدا
view.setFloat64(2, 3.14159); // ۸ بایت...
// صبر — همپوشانی! مراقب offset:
const buf2 = new ArrayBuffer(16);
const v2 = new DataView(buf2);
v2.setInt16(0, 1000); // بایت 0-1
v2.setInt16(2, 2000); // بایت 2-3
v2.setFloat64(4, 2.718); // بایت 4-11
// خواندن:
console.log(v2.getInt16(0)); // 1000
console.log(v2.getInt16(2)); // 2000
console.log(v2.getFloat64(4)); // 2.718
// Endianness — ترتیب بایت:
v2.setInt16(0, 0x1234, false); // big-endian
v2.setInt16(2, 0x1234, true); // little-endian
console.log(v2.getInt16(0, false).toString(16)); // 1234
console.log(v2.getInt16(2, false).toString(16)); // 3412 — برعکس!
Blob — داده فایلمانند
// ساخت:
const blob = new Blob(["متن", " بیشتر"], { type: "text/plain" });
console.log(blob.size); // 15 — بایت
console.log(blob.type); // "text/plain"
// slice — برش:
const part = blob.slice(0, 5, "text/plain");
// چند blob یکی:
const combined = new Blob([blob, new Blob(["آخر"])]);
console.log(combined.size);
// خواندن:
const text = await blob.text();
const buffer = await blob.arrayBuffer();
File — فایل واقعی
// از input:
const fileInput = document.querySelector('input[type=file]');
fileInput.addEventListener("change", (e) => {
const file = e.target.files[0];
console.log(file.name); // نام
console.log(file.size); // حجم بایت
console.log(file.type); // MIME
console.log(file.lastModified); // timestamp
});
// ساخت دستی:
const file = new File(["محتوا"], "note.txt", {
type: "text/plain",
lastModified: Date.now()
});
// File از Blob ارث میبرد — همه متدها + name و lastModified
FileReader — خواندن فایل
const reader = new FileReader();
reader.onload = (e) => {
console.log("نتیجه:", e.target.result);
};
reader.onerror = () => console.log("خطا!");
reader.onprogress = (e) => {
console.log((e.loaded / e.total * 100) + "%");
};
// روشهای خواندن:
reader.readAsText(file); // متن
reader.readAsArrayBuffer(file); // بایتها
reader.readAsDataURL(file); // base64 — برای img
FileReader با Promise
function readFile(file, as = "text") {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => resolve(reader.result);
reader.onerror = reject;
reader["readAs" + as](file);
});
}
// استفاده:
const text = await readFile(file, "Text");
const dataUrl = await readFile(imageFile, "DataURL");
// نمایش تصویر:
const img = document.querySelector("img");
img.src = await readFile(file, "DataURL");
TextEncoder و TextDecoder
// متن → بایت:
const encoder = new TextEncoder();
const bytes = encoder.encode("سلام");
console.log(bytes); // Uint8Array(8) [216, 169, 217, ...]
// هر حرف فارسی ۲ بایت UTF-8
// بایت → متن:
const decoder = new TextDecoder("utf-8");
const text = decoder.decode(bytes);
console.log(text); // "سلام"
// انکودینگهای دیگر:
const winDecoder = new TextDecoder("windows-1256"); // عربی/فارسی قدیمی
const utf16 = new TextDecoder("utf-16le");
تبدیلهای کاربردی
// رشته → Base64:
function toBase64(str) {
const bytes = new TextEncoder().encode(str);
let binary = "";
bytes.forEach(b => binary += String.fromCharCode(b));
return btoa(binary);
}
console.log(toBase64("سلام")); // 2LPZitiv
// Base64 → رشته:
function fromBase64(b64) {
const binary = atob(b64);
const bytes = Uint8Array.from(binary, c => c.charCodeAt(0));
return new TextDecoder().decode(bytes);
}
console.log(fromBase64("2LPZitiv")); // سلام
// عدد ↔ بایت:
const num = 123456;
const b = new Uint8Array(4);
new DataView(b.buffer).setUint32(0, num);
console.log(b); // [0, 1, 226, 64]
console.log(new DataView(b.buffer).getUint32(0)); // 123456
هگزادسیمال
// بایت → هگز:
const bytes = new Uint8Array([0xDE, 0xAD, 0xBE, 0xEF]);
const hex = [...bytes].map(b => b.toString(16).padStart(2, "0")).join(" ");
console.log(hex); // "de ad be ef"
// هگز → بایت:
const hexStr = "deadbeef";
const fromHex = new Uint8Array(
hexStr.match(/.{2}/g).map(h => parseInt(h, 16))
);
console.log(fromHex); // [222, 173, 190, 239]
SharedArrayBuffer و Atomics
// حافظه مشترک بین Workerها:
const shared = new SharedArrayBuffer(4);
const view = new Int32Array(shared);
// در Worker:
// Atomics.store(view, 0, 42); — اتمیک
// اصلی:
Atomics.store(view, 0, 42);
console.log(Atomics.load(view, 0)); // 42
// عملیات اتمیک — بدون Race Condition:
Atomics.add(view, 0, 10);
console.log(Atomics.load(view, 0)); // 52
// انتظار و اطلاع:
// Worker: Atomics.wait(view, 0, 0); — منتظر
// Main: Atomics.notify(view, 0); — بیدار کن
جمعبندی
| ساختار | کاربرد |
|---|---|
ArrayBuffer | حافظه خام بایت |
Uint8Array | بایتهای ساده — رایجترین |
DataView | خواندن چند نوع با Endianness |
Blob | داده فایلمانند |
File | فایل واقعی با نام |
TextEncoder | متن → بایت |
این مبحث بخشی از دوره آموزش کامل جاوا اسکریپت است.