Buffer — alloc, from, concat, encoding
Muammodan boshlaylik
Stream darslarida chunk — bo'lak haqida gapirdik. Encoding bermagan holda readFile <Buffer 53 61 6c 6f 6d> qaytaradi. Bu nima?
Kompyuter ma'lumotni faqat baytlar sifatida saqlaydi. 'Salom' matni ham, rasm ham, video ham — barchasi baytlar. JavaScript da esa string, number, object bor — lekin xom baytlar bilan ishlash uchun maxsus tur yo'q edi.
Node.js Buffer ni aynan shu uchun yaratdi — xom baytlar bilan ishlash uchun.
Buffer nima?
Buffer — xotiradagi qat'iy hajmli baytlar to'plami. Yaratilgandan keyin hajmi o'zgarmaydi.
Nima uchun kerak? Fayl o'qish, tarmoq ma'lumoti, kriptografiya — bularning hammasi baytlar bilan ishlaydi. String esa Unicode — baytlar emas. Shuning uchun ikki dunyo o'rtasida ko'prik kerak. Buffer — o'sha ko'prik.
Disk/Tarmoq → [baytlar] → Buffer → toString() → String
String → Buffer.from() → [baytlar] → Disk/Tarmoq
Buffer.from — mavjud ma'lumotdan Buffer yaratish
// Stringdan:
const buf = Buffer.from('Salom');
console.log(buf);
// <Buffer 53 61 6c 6f 6d> ← har harf baytga aylandi
console.log(buf.length); // 5 ← 5 bayt
// Encoding ko'rsatish (standart: utf8):
const buf2 = Buffer.from('Salom', 'utf8');
const buf3 = Buffer.from('53616c6f6d', 'hex'); // hex dan
const buf4 = Buffer.from('U2Fsb20=', 'base64'); // base64 dan
Massivdan:
const buf = Buffer.from([0x53, 0x61, 0x6c, 0x6f, 0x6d]);
console.log(buf.toString()); // 'Salom'
Buffer.alloc — bo'sh Buffer yaratish
Buffer.alloc — berilgan hajmda bo'sh (nollar bilan to'ldirilgan) Buffer yaratadi.
const buf = Buffer.alloc(10);
console.log(buf);
// <Buffer 00 00 00 00 00 00 00 00 00 00> ← 10 ta nol
// Boshlang'ich qiymat bilan:
const buf2 = Buffer.alloc(5, 0xff);
console.log(buf2);
// <Buffer ff ff ff ff ff>
Nima uchun alloc? Protokollar bilan ishlashda — masalan, TCP paket yaratishda — qat'iy hajmli xotira kerak bo'ladi.
⚠️
Buffer.allocUnsafe(n)ham bor — tezroq, lekin xotira tozalanmaydi (eski ma'lumot bo'lishi mumkin). Xavfsizlik muhim bo'lsa —allocishlatiladi.
Buffer ni o'qish va yozish
const buf = Buffer.alloc(4);
// Yozish:
buf.writeUInt8(255, 0); // 0-pozitsiyaga 255 yoz
buf.writeUInt8(128, 1); // 1-pozitsiyaga 128 yoz
buf.writeUInt16BE(1000, 2); // 2-3 pozitsiyaga 1000 yoz (Big Endian)
console.log(buf);
// <Buffer ff 80 03 e8>
// O'qish:
console.log(buf.readUInt8(0)); // 255
console.log(buf.readUInt8(1)); // 128
console.log(buf.readUInt16BE(2)); // 1000
Bu past darajali operatsiyalar — odatda protokollar (TCP, UDP, binary fayl formatlari) bilan ishlashda kerak bo'ladi.
toString — Buffer ni stringga aylantirish
const buf = Buffer.from('Salom, dunyo!');
buf.toString(); // 'Salom, dunyo!' ← standart utf8
buf.toString('utf8'); // 'Salom, dunyo!'
buf.toString('hex'); // '53616c6f6d2c2064756e796f21'
buf.toString('base64'); // 'U2Fsb20sIGR1bnlvIQ=='
// Qism:
buf.toString('utf8', 0, 5); // 'Salom' ← 0 dan 5 gacha
Buffer.concat — bir nechta Buffer ni birlashtirish
Stream dan kelgan bo'laklarni birlashtirish uchun ko'p ishlatiladi:
const chunks = [];
readStream.on('data', (chunk) => {
chunks.push(chunk);
});
readStream.on('end', () => {
const fullBuffer = Buffer.concat(chunks);
console.log(fullBuffer.toString());
});
Nima uchun + bilan birlashtirmaslik kerak?
// Xato — Buffer + Buffer = string emas:
const result = chunk1 + chunk2;
// '[object Object][object Object]' ← noto'g'ri
// To'g'ri:
const result = Buffer.concat([chunk1, chunk2]);
Hajmni oldindan bilsangiz — tezroq:
const total = chunks.reduce((sum, c) => sum + c.length, 0);
const result = Buffer.concat(chunks, total);
Buffer va String — encoding
Encoding — baytlarni qanday matnга aylantirish qoidasi. Bir xil baytlar turli encoding da turli matn beradi.
const buf = Buffer.from([0xd1, 0x81, 0xd0, 0xb0, 0xd0, 0xbb, 0xd0, 0xbe, 0xd0, 0xbc]);
buf.toString('utf8'); // 'салом' ← to'g'ri (kirill)
buf.toString('latin1'); // 'Ñ\x81алом' ← noto'g'ri encoding
Node.js qo'llab-quvvatlaydigan asosiy encodinglar:
| Encoding | Nima uchun |
|---|---|
utf8 |
Standart, matn uchun |
hex |
Kriptografiya, debug |
base64 |
Email, URL, JSON ichida binary |
base64url |
URL xavfsiz base64 (token uchun) |
latin1 |
Eski tizimlar |
binary |
latin1 bilan bir xil |
Amaliy misol — binary protokol
Ba'zi protokollar (masalan, game server, IoT qurilmalar) ma'lumotni binary formatda yuboradi. Buffer bilan ishlash:
// Protokol: [1 bayt tip] [4 bayt uzunlik] [N bayt ma'lumot]
function createPacket(type, data) {
const dataBuffer = Buffer.from(data, 'utf8');
const packet = Buffer.alloc(1 + 4 + dataBuffer.length);
packet.writeUInt8(type, 0); // tip
packet.writeUInt32BE(dataBuffer.length, 1); // uzunlik
dataBuffer.copy(packet, 5); // ma'lumot
return packet;
}
function parsePacket(packet) {
const type = packet.readUInt8(0);
const length = packet.readUInt32BE(1);
const data = packet.slice(5, 5 + length).toString('utf8');
return { type, data };
}
const packet = createPacket(1, 'Salom');
console.log(parsePacket(packet));
// { type: 1, data: 'Salom' }
Tez-tez uchraydigan xatolar
new Buffer() ishlatish (deprecated):
// Xato — eskirgan, xavfli:
const buf = new Buffer('Salom');
// To'g'ri:
const buf = Buffer.from('Salom');
Buffer uzunligi va string uzunligi farqi:
const str = 'Привет'; // kirill harflari
console.log(str.length); // 6 ← belgilar soni
console.log(Buffer.from(str).length); // 12 ← baytlar soni (har kirill = 2 bayt)
UTF-8 da lotin harflari 1 bayt, kirill/arab/xitoy harflari 2-4 bayt. string.length belgilar sonini beradi, Buffer.length baytlar sonini.
Encoding ko'rsatmaslik:
const buf = Buffer.from('Salom');
buf.toString(); // 'Salom' ← utf8 standart, ishlaydi
// Lekin hex string uchun:
const hexBuf = Buffer.from('53616c6f6d'); // bu string sifatida qabul qilinadi!
hexBuf.toString(); // '53616c6f6d' ← noto'g'ri
// To'g'ri:
const hexBuf = Buffer.from('53616c6f6d', 'hex');
hexBuf.toString(); // 'Salom'
Xulosa
Buffer — Node.js da xom baytlar bilan ishlash uchun. Fayl, tarmoq, kriptografiya — bularning hammasi baytlar bilan ishlaydi, Buffer esa JavaScript va baytlar o'rtasidagi ko'prik.
Kundalik ishda ko'pincha Buffer.from(), buf.toString(), Buffer.concat() ishlatiladi. Past darajali protokollar bilan ishlashda readUInt8, writeUInt32BE kabi metodlar kerak bo'ladi.
Keyingi dars
20-dars: process — argv, env, exit, uncaughtException, SIGINT