|
Buffers represent fixed-length sequences of bytes. They're used for handling binary data like files, network packets, and images.
|
|
|
Creating Buffers
There are several ways to create buffers.
From string (most common)
From array of bytes
Allocate empty buffer (zero-filled)
Allocate without initialization (faster but contains old memory)
|
const buf1 = Buffer.from('Hello World');
console.log('From string:', buf1);
console.log('As string:', buf1.toString());
const buf2 = Buffer.from([72, 101, 108, 108, 111]);
console.log('From array:', buf2.toString());
const buf3 = Buffer.alloc(10);
console.log('Allocated:', buf3);
const buf4 = Buffer.allocUnsafe(10);
console.log('Unsafe:', buf4);
|
|
Buffer Properties
Access buffer length and underlying ArrayBuffer.
|
const buf = Buffer.from('Hello');
console.log('Length:', buf.length);
console.log('Byte length:', buf.byteLength);
console.log('Is Buffer:', Buffer.isBuffer(buf));
|
|
Reading and Writing
Access individual bytes by index.
Modify bytes
|
const readBuf = Buffer.from('ABCDE');
console.log('First byte:', readBuf[0]);
console.log('As char:', String.fromCharCode(readBuf[0]));
const writeBuf = Buffer.alloc(5);
writeBuf[0] = 72;
writeBuf[1] = 105;
console.log('Written:', writeBuf.toString());
|
|
Typed Methods for Numbers
Read and write numbers in various formats.
8-bit integers
16-bit integers (big-endian and little-endian)
32-bit integers
Read them back
|
const numBuf = Buffer.alloc(16);
numBuf.writeUInt8(255, 0);
numBuf.writeInt8(-128, 1);
numBuf.writeUInt16BE(1000, 2);
numBuf.writeUInt16LE(1000, 4);
numBuf.writeUInt32BE(123456, 6);
numBuf.writeInt32LE(-123456, 10);
console.log('UInt8:', numBuf.readUInt8(0));
console.log('Int8:', numBuf.readInt8(1));
console.log('UInt16BE:', numBuf.readUInt16BE(2));
console.log('UInt32BE:', numBuf.readUInt32BE(6));
|
|
Float and Double
Work with floating-point numbers.
|
const floatBuf = Buffer.alloc(12);
floatBuf.writeFloatBE(3.14159, 0);
floatBuf.writeDoubleBE(3.141592653589793, 4);
console.log('Float:', floatBuf.readFloatBE(0));
console.log('Double:', floatBuf.readDoubleBE(4));
|
|
BigInt Support
Read and write 64-bit integers.
|
const bigBuf = Buffer.alloc(8);
bigBuf.writeBigInt64BE(9007199254740993n, 0);
console.log('BigInt:', bigBuf.readBigInt64BE(0));
|
|
String Encoding
Convert between buffers and strings with various encodings.
Create from different encodings
|
const strBuf = Buffer.from('Hello');
console.log('UTF-8:', strBuf.toString('utf8'));
console.log('Hex:', strBuf.toString('hex'));
console.log('Base64:', strBuf.toString('base64'));
const fromHex = Buffer.from('48656c6c6f', 'hex');
const fromBase64 = Buffer.from('SGVsbG8=', 'base64');
console.log('From hex:', fromHex.toString());
console.log('From base64:', fromBase64.toString());
|
|
Copying Buffers
Copy data between buffers.
Clone entire buffer
|
const source = Buffer.from('Hello World');
const target = Buffer.alloc(5);
source.copy(target, 0, 0, 5);
console.log('Copied:', target.toString());
const clone = Buffer.from(source);
|
|
Slicing Buffers
Create views into a buffer (shares memory!).
Modifying slice affects original!
Use subarray (same behavior, modern API)
|
const original = Buffer.from('Hello World');
const slice = original.slice(0, 5);
console.log('Slice:', slice.toString());
slice[0] = 74;
console.log('Original now:', original.toString());
const sub = original.subarray(6, 11);
console.log('Subarray:', sub.toString());
|
|
Concatenating Buffers
Join multiple buffers together.
With total length (more efficient)
|
const part1 = Buffer.from('Hello ');
const part2 = Buffer.from('World');
const combined = Buffer.concat([part1, part2]);
console.log('Combined:', combined.toString());
const efficient = Buffer.concat([part1, part2], 11);
|
|
Comparing Buffers
Compare buffer contents.
|
const a = Buffer.from('ABC');
const b = Buffer.from('ABC');
const c = Buffer.from('ABD');
console.log('a equals b:', a.equals(b));
console.log('a equals c:', a.equals(c));
console.log('a compare c:', a.compare(c));
|
|
Searching in Buffers
Find bytes or strings within buffers.
|
const searchBuf = Buffer.from('Hello World Hello');
console.log('indexOf World:', searchBuf.indexOf('World'));
console.log('lastIndexOf Hello:', searchBuf.lastIndexOf('Hello'));
console.log('includes World:', searchBuf.includes('World'));
|
|
Filling Buffers
Fill buffer with a value.
|
const fillBuf = Buffer.alloc(10);
fillBuf.fill('a');
console.log('Filled:', fillBuf.toString());
fillBuf.fill('xy');
console.log('Pattern:', fillBuf.toString());
fillBuf.fill(0);
console.log('Zeroed:', fillBuf);
|
|
Iterating Buffers
Buffers are iterable.
for...of iterates bytes
entries(), keys(), values()
|
const iterBuf = Buffer.from('ABC');
for (const byte of iterBuf) {
console.log('Byte:', byte, String.fromCharCode(byte));
}
console.log('Entries:', [...iterBuf.entries()]);
|
|
Converting to/from TypedArrays
Buffers share memory with TypedArrays.
Create buffer from TypedArray
|
const buffer = Buffer.from([1, 2, 3, 4]);
const uint8 = new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.length);
console.log('As Uint8Array:', uint8);
const arr = new Uint8Array([5, 6, 7, 8]);
const fromArr = Buffer.from(arr);
|
|
Practical Example: Binary Protocol
Parse a simple binary protocol message.
|
function parseMessage(buffer) {
return {
version: buffer.readUInt8(0),
type: buffer.readUInt8(1),
length: buffer.readUInt16BE(2),
payload: buffer.subarray(4, 4 + buffer.readUInt16BE(2)).toString()
};
}
function createMessage(type, payload) {
const payloadBuf = Buffer.from(payload);
const message = Buffer.alloc(4 + payloadBuf.length);
message.writeUInt8(1, 0);
message.writeUInt8(type, 1);
message.writeUInt16BE(payloadBuf.length, 2);
payloadBuf.copy(message, 4);
return message;
}
const msg = createMessage(1, 'Hello');
console.log('Created message:', msg);
console.log('Parsed:', parseMessage(msg));
|