টাইপস্ক্রিপ্টে `DataView`

টাইপস্ক্রিপ্টে `DataView`

এই প্রবন্ধটি টাইপস্ক্রিপ্টে DataView ব্যাখ্যা করে।

আমরা TypeScript-এ DataView-এর বেসিক থেকে ব্যবহারিক প্রয়োগ পর্যন্ত ধাপে ধাপে ব্যাখ্যা করব।

YouTube Video

টাইপস্ক্রিপ্টে DataView

TypeScript-এ DataView ব্যবহার করে আপনি একটি ArrayBuffer-এর ওপর সূক্ষ্ম মাত্রার বাইট স্তরের পঠন ও লেখন কাজ করতে পারবেন। DataView খুব নিম্ন স্তরের বাইনারি প্রসেসিং যেমন প্রোটোকল ইমপ্লিমেন্টেশন, বাইনারি ফাইল বিশ্লেষণ এবং WebSocket দিয়ে বাইনারি ডেটা আদান-প্রদানে অত্যন্ত উপযোগী।

মূল ধারণাসমূহ: ArrayBuffer, TypedArray, এবং DataView-র মধ্যে পার্থক্য

ArrayBuffer হল একটি মৌলিক ডেটা স্ট্রাকচার যা নির্দিষ্ট দৈর্ঘ্যের বাইট সিকোয়েন্স সংরক্ষণে ব্যবহৃত হয়। TypedArray যেমন Uint8Array হল এমন ভিউ, যা বাফারকে নির্দিষ্ট টাইপের অ্যারে হিসেবে দেখে এবং সেখানে প্রতিটি উপাদান নির্দিষ্ট একটাই টাইপের হয়।

অন্যদিকে, DataView একটি নমনীয় ভিউ যা আপনাকে যেকোন ডেটা টাইপের মান যেকোনো অফসেট অবস্থানে পড়া ও লেখা করার সুবিধা দেয়। এটি নির্দিষ্ট টাইপ ধরে নেয় না এবং বাইট স্তরে সূক্ষ্ম নিয়ন্ত্রণের সুযোগ দেয় বলে, বাইনারি প্রোটোকল বিশ্লেষণ ও নিম্ন-স্তরের প্রসেসিংয়ের জন্য উপযুক্ত।

নিম্নে ArrayBuffer তৈরি করে এবং তা থেকে Uint8ArrayDataView তৈরি করার একটি উদাহরণ দেখানো হয়েছে।

 1// Create an ArrayBuffer (8 bytes)
 2const buffer = new ArrayBuffer(8);
 3
 4// Create a Uint8Array view (easy to manipulate individual bytes)
 5const u8 = new Uint8Array(buffer);
 6u8[0] = 0x12;
 7u8[1] = 0x34;
 8
 9// Create a DataView (allows reading/writing any type at any offset)
10const dv = new DataView(buffer);
11
12// Read a 16-bit unsigned integer (big-endian assumed if second argument is omitted)
13console.log(dv.getUint16(0)); // 0x1234
  • এই কোডে, একই বাফারে দুটি আলাদা টাইপের ভিউ—Uint8Array এবং DataView—একসাথে ব্যবহৃত হয়েছে। DataView ব্যবহার করে আপনারা ইচ্ছামতো অফসেট ও এনডিয়াননেস নির্ধারণ করে নমনীয়ভাবে মান পড়া এবং লেখা করতে পারেন।

DataView-এর প্রধান মেথডসমূহ

DataView হল একটি ইন্টারফেস যা ArrayBuffer-কে বাইট স্তরে ম্যানিপুলেট করার জন্য ব্যবহৃত হয় এবং এটি ইন্টিজার, ফ্লোটিং-পয়েন্ট ইত্যাদি বিভিন্ন ডেটা টাইপ পড়া ও লেখার মেথড সরবরাহ করে।

প্রধান মেথডগুলো হচ্ছে:।

  • পড়া (Read): getUint8, getInt8, getUint16, getInt16, getUint32, getInt32, getFloat32, getFloat64
  • লেখা (Write): setUint8, setInt8, setUint16, setInt16, setUint32, setInt32, setFloat32, setFloat64

এই সব মেথডের প্রথম আর্গুমেন্ট হিসেবে 'বাইট অফসেট' থাকে: get সংশ্লিষ্ট অবস্থানের মান পড়ে এবং set ঐ স্থানে মান লেখে। ১৬, ৩২ অথবা ৬৪-বিট ডেটা ব্যবহারে, দ্বিতীয় আর্গুমেন্ট হিসেবে এনডিয়াননেসও নির্ধারণ করতে পারেন। প্র্যাক্টিক্যালে, ডেটা স্পেসিফিকেশনের সাথে মিল রেখে সবসময় এনডিয়াননেস নির্দিষ্ট করা সবচেয়ে নিরাপদ।

নিম্নের উদাহরণে দেখানো হয়েছে কিভাবে একটি ৩২-বিট ইন্টিজার ও ৩২-বিট ফ্লোটিং পয়েন্ট নাম্বার লিটল এনডিয়ান ফরম্যাটে বাফারে লেখা ও পরে একই ফরম্যাটে পড়া যায়।

 1const buf = new ArrayBuffer(12); // Enough space for integer + float
 2const view = new DataView(buf);
 3
 4// Write a 32-bit unsigned integer at offset 0 (little-endian)
 5view.setUint32(0, 305419896, true); // 305419896 = 0x12345678
 6
 7// Read the same 32-bit unsigned integer back from offset 0 (little-endian)
 8const intVal = view.getUint32(0, true);
 9console.log(intVal); // 305419896
10
11// Write a 32-bit floating number at offset 4 (little-endian)
12view.setFloat32(4, 3.1415926, true);
13
14// Read the 32-bit floating number back from offset 4 (little-endian)
15const floatVal = view.getFloat32(4, true);
16console.log(floatVal); // 3.1415926 (approx)
  • স্পষ্টভাবে এনডিয়াননেস উল্লেখ করলে বিভিন্ন প্ল্যাটফর্ম ও বাইনারি স্পেসিফিকেশন অনুযায়ী সামঞ্জস্য নিশ্চিত করা যায়।

এনডিয়াননেস (বাইটের বিন্যাস) সংক্রান্ত

কিছু প্রোটোকল, যেমন নেটওয়ার্কিং সংক্রান্ত, বিগ-এনডিয়ান ব্যবহার করে; আবার বেশিরভাগ CPU ও ফাইল ফরম্যাট লিটল-এনডিয়ান হয়ে থাকে। DataView-এ দ্বিতীয় আর্গুমেন্ট true হলে তাকে লিটল এনডিয়ান হিসাবে ধরে; false বা বাদ দিলে বিগ এনডিয়ান হিসাবে ধরে।

নিচের উদাহরণে, আপনি দেখতে পাবেন কীভাবে মেমরিতে থাকা বাইট অ্যারে পরিবর্তিত হয় যখন একই সংখ্যা big-endian এবং little-endian উভয় ফরম্যাটে লেখা হয়।

 1const b = new ArrayBuffer(4);
 2const a = new Uint8Array(b);
 3const dv = new DataView(b);
 4
 5// Write in big-endian order
 6dv.setUint32(0, 0x0A0B0C0D, false); // big-endian
 7console.log([...a]); // [10, 11, 12, 13]
 8
 9// Write the same value in little-endian order
10dv.setUint32(0, 0x0A0B0C0D, true); // little-endian
11console.log([...a]); // [13, 12, 11, 10]
  • বাইট বিন্যাস বিগ এনডিয়ান ও লিটল এনডিয়ান অনুযায়ী কিভাবে পরিবর্তিত হয় তা বোঝা গেলে যোগাযোগ ডেটা বা বাইনারি ফরম্যাট বিশ্লেষণ করা সহজ হবে।

স্ট্রিং ইনপুট/আউটপুট (TextEncoderDecoder-এর সংযুক্ত ব্যবহারে)

DataView সংখ্যাসূচক মান পড়া-লেখায় খুবই ভাল, কিন্তু এটি সরাসরি স্ট্রিং হ্যান্ডল করতে পারে না। সাধারণত TextEncoder বা TextDecoder ব্যবহার করে স্ট্রিংকে এনকোড (যেমন UTF-8-এ) করা হয় এবং তারপর Uint8Array দিয়ে বাফারে কপি করা হয়। নিম্নের অভিযানে দেখানো হয়েছে কিভাবে একটি UTF-8 স্ট্রিং বাফারে লেখা ও পরে তা পুনরায় পড়া যায়।

 1const encoder = new TextEncoder();
 2const decoder = new TextDecoder();
 3
 4const str = "\u3053\u3093\u306b\u3061\u306f";
 5const encoded = encoder.encode(str); // Uint8Array (UTF-8 encoded bytes)
 6
 7// Create a buffer and write the encoded string bytes into it
 8const buf2 = new ArrayBuffer(encoded.length);
 9const u8v = new Uint8Array(buf2);
10u8v.set(encoded);
11
12// Read the bytes and decode them back into a string
13const decodedStr = decoder.decode(new Uint8Array(buf2));
14console.log(decodedStr);
  • স্ট্রিংকে বাইনারি রূপান্তর করে এবং প্রয়োজনে তার দৈর্ঘ্য যুক্ত করে, পরিবর্তনশীল দৈর্ঘ্যের স্ট্রিং সংরক্ষণ করা যায়।

ব্যবহারিক উদাহরণ: একটি কাস্টম বাইনারি ফরম্যাট এনকোড/ডিকোড করা

নিম্নে, আমরা একটি সহজ মেসেজ ফরম্যাট সংজ্ঞায়িত করছি যাতে একটি ভার্সন নম্বর, আইডি, এবং নাম রয়েছে। আমরা একটি এনকোডিং প্রসেস বাস্তবায়ন করি যা মেসেজকে বাইনারি ডেটায় রূপান্তর করে, এবং একটি ডিকোডিং প্রসেস যা বাইনারি থেকে মূল অবজেক্ট পুনরুদ্ধার করে। এই মেসেজ ফরম্যাটে, প্রথম বাইটটি ভার্সন সংরক্ষণ করে, পরবর্তী ৪টি বাইট little-endian ফরম্যাটে আইডি সংরক্ষণ করে, তার পরের বাইটে নামের দৈর্ঘ্য থাকে, এবং শেষ পর্যন্ত, UTF-8 এনকোড করা নাম সংরক্ষিত হয়।

 1// Encode an object into a binary message
 2function encodeMessage(msg: { version: number; id: number; name: string }): ArrayBuffer {
 3  const encoder = new TextEncoder();
 4  const nameBytes = encoder.encode(msg.name);
 5  const total = 1 + 4 + 1 + nameBytes.length;
 6  const buf = new ArrayBuffer(total);
 7  const dv = new DataView(buf);
 8  let offset = 0;
 9
10  dv.setUint8(offset, msg.version); offset += 1;      // write version
11  dv.setUint32(offset, msg.id, true); offset += 4;    // write ID (little-endian)
12  dv.setUint8(offset, nameBytes.length); offset += 1; // write name length
13
14  // write name bytes
15  new Uint8Array(buf, offset).set(nameBytes);
16  return buf;
17}
18
19// Decode a binary message back into an object
20function decodeMessage(buf: ArrayBuffer) {
21  const dv = new DataView(buf);
22  let offset = 0;
23
24  const version = dv.getUint8(offset); offset += 1;   // read version
25  const id = dv.getUint32(offset, true); offset += 4; // read ID (little-endian)
26  const nameLen = dv.getUint8(offset); offset += 1;   // read name length
27
28  // extract name bytes
29  const nameBytes = new Uint8Array(buf, offset, nameLen);
30  const decoder = new TextDecoder();
31  // decode UTF-8 string
32  const name = decoder.decode(nameBytes);
33
34  return { version, id, name };
35}
36
37// Example usage
38const packed = encodeMessage({ version: 1, id: 42, name: "Alice" });
39const unpacked = decodeMessage(packed);
40console.log(unpacked); // { version: 1, id: 42, name: "Alice" }
  • এটি একটি আদর্শ ইমপ্লিমেন্টেশন, যাতে পরিবর্তনশীল দৈর্ঘ্যের স্ট্রিং থাকা একটি বেসিক মেসেজ ফরম্যাট হ্যান্ডল করা যায়; এবং এটি নেটওয়ার্ক কমিউনিকেশন বা কাস্টম বাইনারি ফাইল ডিজাইনে ব্যবহারিকভাবে প্রয়োগ করা যায়।

সতর্কতা ও সেরা চর্চা

DataView দিয়ে বাইনারি ডেটা ব্যবহারে কেবল মান পড়া-লেখা ছাড়াও আরও কিছু ব্যবহারিক বিষয় যেমন নিরাপত্তা, এনডিয়াননেসের ধারাবাহিক ব্যবহার, ও টাইপ সঠিকভাবে ব্যবস্থাপনা করা জরুরি। বিশেষত, বাহ্যিক উৎস থেকে প্রাপ্ত বাইনারি ডেটা বা বড় ইন্টিজার ব্যবহারে ভুল পঠন বা বাফার ওভাররান যেন না হয়, সেজন্য কোড সাবধানতার সাথে তৈরি করতে হবে। বাস্তব ব্যবহারের জন্য মনে রাখার মতো কিছু গুরুত্বপূর্ণ বিষয় নিচে দেওয়া হল।

  • বাউন্ডারি চেক যদি অফসেট বা সাইজ বাফারের সীমা অতিক্রম করে, তখন DataView এক্সেপশন ছুড়ে দেয়। অনির্ভরযোগ্য বাইনারি ডেটা ব্যবহারে সর্বদা দৈর্ঘ্য যাচাই করুন।

  • সবসময় এনডিয়াননেস নির্ধারণ করুন আপনার কোডে লিটল এনডিয়ান অথবা বিগ এনডিয়ান স্পষ্ট ও ধারাবাহিকভাবে নির্ধারণ করুন।

  • টাইপের সামঞ্জস্যতা জাভাস্ক্রিপ্টের সকল নাম্বার ৬৪-বিট IEEE-754 ফ্লোটিং-পয়েন্ট মান। getUint32-এর মতো মেথড যথাযথভাবে কাজ করে, কিন্তু getUint64 নেই, তাই ৬৪-বিট ইন্টিজারের জন্য বিশেষ ব্যবস্থা নিতে হয়।

  • ৬৪-বিট ইন্টিজার ব্যবস্থাপনা ৬৪-বিট ইন্টিজার ব্যবস্থাপনায় BigInt ব্যবহার অথবা মানটি দুটি—উচ্চ ও নিম্ন—৩২-বিট ভাগে বিভক্ত করতে হবে। নিম্নে একটি ৬৪-বিট আনসাইনড ইন্টিজার পড়ার সহজ উদাহরণ দিলাম।

1function getUint64(dv: DataView, offset: number, littleEndian = true): bigint {
2  const low = BigInt(dv.getUint32(offset, littleEndian));
3  const high = BigInt(dv.getUint32(offset + 4, littleEndian));
4  return littleEndian ? (high << 32n) | low : (low << 32n) | high;
5}
  • BigInt ব্যবহার করে ৬৪-বিটের চেয়েও বড় ইন্টিজারের নিরাপদ ব্যবস্থাপনাও করা যায়।

Node.js-এ ব্যবহার (Buffer-এর সাথে ইন্টারঅপারেশন)

যদিও Buffer সাধারণত Node.js-এ ব্যবহৃত হয়, কিন্তু ArrayBuffer এবং DataView এর মধ্যে রূপান্তর করাও সহজ। Buffer অবজেক্টের buffer প্রপার্টি অথবা Uint8Array কনস্ট্রাক্টর রূপান্তরের জন্য ব্যবহার করুন।

1// Node.js: Buffer -> ArrayBuffer
2const nodeBuf = Buffer.from([1,2,3,4]);
3const arrBuf = nodeBuf.buffer.slice(nodeBuf.byteOffset, nodeBuf.byteOffset + nodeBuf.byteLength);
4const dvNode = new DataView(arrBuf);
5console.log(dvNode.getUint16(0));
  • এটি Node.js এবং ব্রাউজারের মধ্যে বাইনারি ডেটা বিনিময়ের একটি মাধ্যম হিসাবে ব্যবহার করা যেতে পারে।

সারসংক্ষেপ

DataView হল শক্তিশালী একটি ব্যবস্থা, যা বাইনারি ডেটা স্বাধীনভাবে পড়া-লেখায় সক্ষম—বিশেষত এনডিয়াননেস নির্ধারণ বা ইচ্ছামতো পজিশনে অ্যাক্সেস দরকার হলে। ArrayBuffer, TypedArrayDataView একত্রে ব্যবহার করে TypeScript-এ আপনি নিখুঁত ও নমনীয়ভাবে বাইনারি ডেটা ব্যবস্থাপনা করতে পারেন, যার ফলে প্রোটোকল ইমপ্লিমেন্টেশন থেকে ফাইল বিশ্লেষণ পর্যন্ত বিস্তৃত কাজ সম্ভব। স্ট্রিং এনকোডিং ও ৬৪-বিট ইন্টিজার পরিচালনা অন্তর্ভুক্ত করলে, আরও ব্যবহারিক বাইনারি অপারেশনও করতে পারবেন।

আপনি আমাদের ইউটিউব চ্যানেলে ভিজ্যুয়াল স্টুডিও কোড ব্যবহার করে উপরের নিবন্ধটি অনুসরণ করতে পারেন। দয়া করে ইউটিউব চ্যানেলটিও দেখুন।

YouTube Video