Buffer

The buffers module provides a way of handling streams of binary data. The Buffer object is a global object in Node.js, and it is not necessary to import it using the require keyword. Before we go to the buffer we need to know what is binary data and stream.

Binary Data

Computer can understand only combination of 1 and 0 and nothing else. So everything is converted to that form so that a computer can understand. Everything means everything, like numbers, string, images, videos etc. All these data is loaded in the memory in Binary format. The data in Binray format is called Binary Data.

Stream of Binary Data

Stream in Node.js simply means a sequence of data being moved from one point to the other over time. The whole concept is, you have a huge amount of data to process, but you don’t need to wait for all the data to be available before you start processing it. Basically, this big data is broken down and sent in chunks. The movement of binary data from one location to another is called Stream of Binary data. For example, data movement from disk to file.

Buffer

We’ve seen that a stream of data is the movement of data from one point to the other, but how exactly are they moved?

Typically, the movement of data is usually with the intention to process it, or read it, and make decisions based on it. But there is a minimum and a maximum amount of data a process could take over time. The whole data is not processed at once, instead the first chunk of the processed first, after the processing is finished the next chunk of data is being processed. And this way it contines until all the data is being processed. So there are basically two process:

But, if the loading time is less than processing time, then the next chunk of data needs to wait somewhere for the previous chunk to be finished processing.

On the other hand, if the process is consuming the data faster than it arrives, the few data that arrive earlier need to wait for a certain amount of data to arrive before being sent out for processing.

That “waiting area” is the buffer! It is a small physical location in your computer, usually in the RAM, where data are temporally gathered, wait, and are eventually sent out for processing during streaming.

In Node.js you can use buffer (a physical location in RAM), to store binary data so that you can send these data for processing in later time.

A typical example where you could see buffer in action is when you’re streaming a video online. If your internet connection is fast enough, the speed of the stream will be fast enough to instantly fill up the buffer and send it out for processing, then fill another one, and send it out, then another, and yet another… till the stream is finished.

But if your connection is slow, after processing the first set of data that arrived, the video player will display a loading icon, or display the text “buffering”, which means gathering more data, or waiting for more data to arrive. And when the buffer is filled up and processed, the player shows the data, the video. While playing that, more data will continue to arrive and wait in the buffer.

If the player is done processing or playing the previous data, and the buffer is not yet filled up, the text “buffering” will be displayed again, waiting to gather more data to process.

With the help of Node.js we can manipulate or interact with the binary data being processed. So let's see what we can do with the buffer in Node.js.

Creating Buffer

It is possible to create your own buffer. It doesn't mean that you can create a physical location. It means it reserves a block in the memory that can be used as a buffer. Depending on what you want to achieve, there are different ways to create a buffer.

There are three ways you can create buffer:

Buffer.alloc()

This method takes an integer value as an argument which specifies the number of bytes to be alocated in the memory.

let buffer = Buffer.alloc(10); // Reserves 10 bytes in Memory as the Buffer
console.log(buffer);
// <Buffer 00 00 00 00 00 00 00 00 00 00>

This method clears out everything within the reserved space. It means it first allocates the memory and then deletes the data. So initially the buffer contains all 0s. Now you can assign a value to that buffer. Let's assign a string.

To assign some value to the buffer you can use one of the following:

We will get into details of these methods later. But you can get the basic idea what it does. These method writes the data into the buffer.

let buffer = Buffer.alloc(10);
buffer.write("Santanu");
console.log(buffer);
// <Buffer 53 61 6e 74 61 6e 75 00 00 00>

Notice the output, the last three bytes are still 0. So the data is written from the first index. The first byte shows 53. Actually in memory it is stored in binary equivalent. But why 53? By default Node.js uses UTF-8 encoding system. The UTF-8 representation of the string is converted into binary form and then it is stored in the memory. The method console.log automatically converts that binary form into hexadecimal representation. So the letter S represents 53, a represents 61 and so on. This way in memory the Binary form of UTF-8 encoding representation is stored. But console.log is converting that binary form to hexadecimal representation. But still, the hexadecimal representation is not human readable. To make it human readable format you can use toString() method.

let str = buffer.toString();
console.log(str); // Santanu

Let's furthur assign some value:

let buffer = Buffer.alloc(10);
buffer.write("Santanu");
buffer.write("Bera");
console.log(buffer);
// <<uffer 42 65 72 61 61 6e 75 00 00 00>
console.log(buffer.toString());
// Beraanu

Notice the output, if you assign value again using write(), it will again write it from the start of the buffer over the pre-existing data. So first we had Santanu, and then Bera. As already there was data before writing Bera, it wasn't cleared out. So you can still see the remaining byte what it contains.

Now you have the idea what Buffer.alloc() method does. Let's look at the full syntax:

Buffer.alloc(size[, fill[, encoding]])

Here fill is the data which will be writted to the buffer. If it is not specified the buffer will not contain anything. The default is 0, it means by default the buffer will be filled with all 0s.

The last optional argument is encoding system in which the binary conversion will take place, which we have talked earlier. Node.js supports various encoding system. By default it is utf8. We will talk about Encoding system in later chapter.

Here is an example:

const buf = Buffer.alloc(5, 'a');
console.log(buf);
// Prints: <Buffer 61 61 61 61 61>

Buffer.allocUnsafe()

This method is same as alloc(), but the reserved space is not cleared out. The allocated space might contain some data which can be sensitive. Just like alloc() it takes a integer value to specify the number of bytes to reserve.

let buffer = Buffer.allocUnsafe(10);
console.log(buffer);
// <Buffer 00 ff ff ff 00 00 00 00 00 00>

Note that in the above example, we haven't write anything to the buffer but the second, third, and fourth byte contains some data. Actually Node.js looks for some unused memory in the RAM. But that unused space might contain some data which was being used by another application, and that applciation didn't clear the space before terminating. So that data is left out in the RAM which are not referenced by any pointer. These data might be very sensitive. So there is security risk of using Buffer.allocUnsafe() method.

Another difference is that allocUnsafe is faster than alloc method. So alloc is slow-safe way of using buffer, and allcUnsafe is fast-unsafe way of using Buffer.

If you want to use allocUnsafe(), you should explicitily reset the allocated space, in other words delete all the data, or cleared out the data. You can do that using fill() method.

buffer.fill(0);
console.log(buffer);
// <Buffer 00 00 00 00 00 00 00 00 00 00>

The full syntax is:

Buffer.allocUnsafe(size)

We will go deeper over why we should use Buffer.allocUnsafe() instead of Buffer.alloc() method after the concept of pullSize.

Buffer.from()

Another way of creating a Buffer is to use the syntax Buffer.from(). But based on the datatype you can pass different argument.

Buffer.from(Array)

You can create buffer from a provided array. The method Buffer.from() Allocates a new Buffer using an array of octets.

const buf = Buffer.from([0x62, 0x75, 0x66, 0x66, 0x65, 0x72]);

The above method creates a buffer using provided array of octal values.

let buffer = Buffer.from([1, 2, 3]);
console.log(buffer); // <Buffer 01 02 03>

Buffer.from(Buffer)

You can also create buffer from another buffer. After calling that method, the resulting buffer will be identical as the provided buffer as the argument. But they are seperated, it means any changes made to the copied buffer won't affect anything to the buffer from which the new buffer is created.

const buffer1 = Buffer.from('buffer');
const buffer2 = Buffer.from(buffer1);

buffer1[0] = 0x61;

console.log(buffer1.toString());
// Prints: auffer
console.log(buffer2.toString());
// Prints: buffer

Buffer.from(string[, encoding])

Creates a new Buffer containing string. The encoding parameter identifies the character encoding of string.

const buffer1 = Buffer.from('this is a tést');
const buffer2 = Buffer.from('7468697320697320612074c3a97374', 'hex');

console.log(buffer1.toString());
// Prints: this is a tést
console.log(buffer2.toString());
// Prints: this is a tést
console.log(buffer1.toString('ascii'));
// Prints: this is a tC)st

Others

There are other two variation of creating Buffer:

Which we will cover later in this section.

Buffer.isBuffer()

To check if a Buffer is a Buffer of not, use the method isBuffer():

let buffer1 = Buffer.from("Santanu", 'utf8');
let notBuffer = {};
console.log(Buffer.isBuffer(buffer1)); // true
console.log(Buffer.isBuffer(notBuffer)); // false

buffer.fill()

This method is used to fill the Buffer. The syntax is :

buffer.fill(value[, offset[, end]][, encoding])

This method returns the buffer object on which it was called.

const b = Buffer.allocUnsafe(50).fill('h');
console.log(b.toString());
// Prints: hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh

One thing to remember is that, value is coerced to a uint32 value if it is not a String or Integer. If the final write of a fill() operation falls on a multi-byte character, then only the first bytes of that character that fit into buffer are written.

// Fill a `Buffer` with a two-byte character.

console.log(Buffer.allocUnsafe(3).fill('\u0222'));
// Prints: <Buffer c8 a2 c8>

If value contains invalid characters, it is truncated.

buffer.length

Returns the amount of memory allocated for buffer in bytes. Note that this does not necessarily reflect the amount of "usable" data within buffer.

// Create a `Buffer` and write a shorter ASCII string to it.

const buffer = Buffer.alloc(1234);

console.log(buffer.length);
// Prints: 1234

buffer.write('some string', 0, 'ascii');

console.log(buffer.length);
// Prints: 1234

Note, the length property is mutable. It means you can change it. But doing it can cause unexpected result.

buffer.toString([encoding[, start[, end]]])

This method returns the string representation of the buffer. This method decodes buffer to a string according to the specified character encoding in encoding. start and end may be passed to decode only a subset of buffer.

const buffer1 = Buffer.allocUnsafe(26);

for (let i = 0; i < 26; i++) {
  // 97 is the decimal ASCII value for 'a'
  buffer1[i] = i + 97;
}

console.log(buffer1.toString('ascii'));
// Prints: abcdefghijklmnopqrstuvwxyz
console.log(buffer1.toString('ascii', 0, 5));
// Prints: abcde

const buffer2 = Buffer.from('tést');

console.log(buffer2.toString('hex'));
// Prints: 74c3a97374
console.log(buffer2.toString('utf8', 0, 3));
// Prints: té
console.log(buffer2.toString(undefined, 0, 3));
// Prints: té

buffer.write()

buffer.write(string[, offset[, length]][, encoding])

It returns the number of bytes written to the buffer.

The length parameter is the number of bytes to write. If buf did not contain enough space to fit the entire string, only a partial amount of string will be written.

const buf = Buffer.allocUnsafe(256);

const len = buf.write('\u00bd + \u00bc = \u00be', 0);

console.log(`${len} bytes: ${buf.toString('utf8', 0, len)}`);
// Prints: 12 bytes: ½ + ¼ = ¾

Here, it takes 12 bytes in total. 9 bytes for each character and among them three character takes 2 byte space. So 9 + 3 = 12 bytes.

So there is a differece between fill() and write() method. fill() method only accepts one byte character, if two byte character is provided, then only the first byte is used to fill the buffer. On the other hand, the write() methods can write two bytes character if there's enough space to write to the buffer.

Buffers and iteration

Buffer instances can be iterated over using for..of syntax:

const buf = Buffer.from([1, 2, 3]);

// Prints:
//   1
//   2
//   3
for (const b of buf) {
  console.log(b);
}

Here is another example:

let buffer = Buffer.alloc(10);
buffer.write("Santanu");
for(let byte of buffer){
	console.log(byte);
}
console.log(buffer);

And here is the output you will get:

83
97
110
116
97
110
117
0
0
0
// <Buffer 53 61 6e 74 61 6e 75 00 00 00>

Note that in the above example, two outputs are different. Let me explain: If you buffer directly you will get Buffer object with the values which is in hexadecimal format. So the last line is in hexadecimal representation of "Santanu". And if you iterate a buffer using for..of loop, and console.log each byte. You will get utf8 encoded representation of the byte. So to makes the output similar we can convert each byte to it's equivalent hexadecimal representation.

console.log(parseInt(byte).toString(16));

Now both values are in hexadecimal format. Another thing to note that, the data type of byte is number. It contains, the utf8 equivalent number of the string. You can check it:

let buffer = Buffer.alloc(10);
buffer.write("Santanu");
for(let byte of buffer){
	if (byte == 83) {
		console.log("Okay");
	}
}
console.log(buffer);

// Okay
// <Buffer 53 61 6e 74 61 6e 75 00 00 00>

So if you console.log buffer directly, you will get readable string representation of the Buffer. Where each byte contains the hexadecimal format of the string. But internally, it is stored in utf8 format.

let buffer = Buffer.from("Santanu");
console.log(buffer[i]); // 83, Not 53

buffer[index]

The index operator [index] can be used to get and set the octet at position index in buffer. The values refer to individual bytes, so the legal value range is between 0x00 and 0xFF (hex) or 0 and 255 (decimal).

// Copy an ASCII string into a `Buffer` one byte at a time.

const str = 'Node.js';
const buffer = Buffer.allocUnsafe(str.length);

for (let i = 0; i < str.length; i++) {
  buffer[i] = str.charCodeAt(i);
}

console.log(buffer.toString('ascii'));
// Prints: Node.js

buffer.keys()

Creates and returns an iterator of buf keys (indices).

const buf = Buffer.from('buffer');

for (const key of buf.keys()) {
  console.log(key);
}
// Prints:
//   0
//   1
//   2
//   3
//   4
//   5

Note that, a buffer is not an object, so you will never except anything but number as the key. So it always returns an iterator of indices. Each index represents the specified byte into the buffer.

Note that, this method doesn't return array. It returns iterator but not an array. So most array method won't work on this type. So the following won't work:

let buffer = Buffer.alloc(10);
buffer.write("Santanu");
let keys = buffer.keys();
console.log(Array.isArray(keys)); // false

console.log(keys[2]); // Won't work, returns undefined.

You can use this iterator to iterate over the buffer and access it's content:

for (const key of buffer.keys()) {
  console.log(buffer[key]);
}

There is another thing to remember that, this method returns the indices of whole buffer, regardless of how many bytes has been written into it. For example:

let buffer = Buffer.alloc(10);
buffer.write("Santanu"); // 7 bytes long

for(let key of buffer.keys()){
	console.log(key);
}


// Prints:
// 0
// 1
// 2
// 3
// 4
// 5
// 6
// 7
// 8
// 9

This method can be used as a shortcut way to iterate over a buffer:

for (const key of buffer.keys()) {
  console.log(buffer[key]);
}

// Same as 

let i = 0;
while(i < buffer.length){
	console.log(buffer[i++]);
}

buffer.values()

Creates and returns an iterator for buffer values (bytes). This function is called automatically when a Buffer is used in a for..of statement.

const buffer = Buffer.from('buffer');

for (const value of buffer.values()) {
  console.log(value);
}
// Prints:
//   98
//   117
//   102
//   102
//   101
//   114

// In the following example, the buffer.values() is called automatically:
for (const value of buffer) {
  console.log(value);
}
// Prints:
//   98
//   117
//   102
//   102
//   101
//   114

Like buffer.keys(), this method returns the values of whole buffer, regardless of how many bytes has been written into it.

Like buffer.keys(), this method returns an iterator, not an array. So the following won't work:

let buffer = Buffer.alloc(10);
buffer.write("Santanu");

let values = buffer.values();
console.log(values[3]); // undefined

buffer.entries()

Creates and returns an iterator of [index, byte] pairs from the contents of buffer.

// Log the entire contents of a `Buffer`.

const buf = Buffer.from('buffer');

for (const pair of buf.entries()) {
  console.log(pair);
}
// Prints:
//   [0, 98]
//   [1, 117]
//   [2, 102]
//   [3, 102]
//   [4, 101]
//   [5, 114]

Similar to the buffer.keys() and buffer.values(), this method contains the whole pair of the buffer, regardless of how many bytes has been written to it.

let buffer = Buffer.allocUnsafe(10);
buffer.fill(0);
buffer.write("Santanu");
let entries = buffer.entries();
for (const pair of buffer.entries()) {
  console.log(pair[1]);
}

// Prints
// [ 0, 83 ]
// [ 1, 97 ]
// [ 2, 110 ]
// [ 3, 116 ]
// [ 4, 97 ]
// [ 5, 110 ]
// [ 6, 117 ]
// [ 7, 0 ]
// [ 8, 0 ]
// [ 9, 0 ]

buffer.concat()

Buffer.concat(list[, totalLength])

Returns a new Buffer which is the result of concatenating all the Buffer instances in the list together. If the list has no items, or if the totalLength is 0, then a new zero-length Buffer is returned.

If totalLength is not provided, it is calculated from the Buffer instances in list. This however causes an additional loop to be executed in order to calculate the totalLength, so it is faster to provide the length explicitly if it is already known.

If totalLength is provided, it is coerced to an unsigned integer. If the combined length of the Buffers in list exceeds totalLength, the result is truncated to totalLength.

// Create a single `Buffer` from a list of three `Buffer` instances.

const buffer1 = Buffer.alloc(10);
const buffer2 = Buffer.alloc(14);
const buffer3 = Buffer.alloc(18);
const totalLength = buffer1.length + buffer2.length + buffer3.length;

console.log(totalLength);
// Prints: 42

const bufA = Buffer.concat([buffer1, buffer2, buffer3], totalLength);

console.log(bufA);
// Prints: <Buffer 00 00 00 00 ...>
console.log(bufA.length);
// Prints: 42

Buffer.compare()

Compares buffer1 to buffer2 typically for the purpose of sorting arrays of Buffer instances. This is equivalent to calling buffer1.compare(buffer2).

const buf1 = Buffer.from('1234');
const buf2 = Buffer.from('0123');
const arr = [buf1, buf2];

console.log(arr.sort(Buffer.compare));
// Prints: [ <Buffer 30 31 32 33>, <Buffer 31 32 33 34> ]
// (This result is equal to: [buf2, buf1])

The conversion happens byte by byte. If both values are same, then it returns 0. Internally each bytes are represented as utf8 representation code of the string. Which is a number. For example, for the letter "S", the binary form of the utf8 equivalent which is 83 is stored in the memorey. This numeric number is being compared with the another buffer's numeric representation. And according to it, the result is then calculated.

let buffer1 = Buffer.from("Santanu");
let buffer2 = Buffer.from("Santanu");
console.log(Buffer.compare(buffer1, buffer2)); // 0

If the byte of the first buffer is greater than the byte of second buffer, then it returns 1. If the byte of the first buffer is less then the byte of second buffer, it returns -1.

let buffer1 = Buffer.from("SAntanu");
let buffer2 = Buffer.from("Santanu");
console.log(Buffer.compare(buffer1, buffer2)); // -1
console.log(Buffer.compare(buffer2, buffer1)); // 1

In the above example, the utf8 code of a is 97, and A is 65. So small letter is bigger than the capital letter. And that's why buffer2 is considered as bigger.

Note that, if both buffer contains same value, and if a buffer contains unused bytes, it is considered as bigger. Here is the example:

let buffer1 = Buffer.alloc(10);
buffer1.write("Santanu");

let buffer2 = Buffer.from("Santanu");

console.log(Buffer.compare(buffer1, buffer2)); // 1

In the above example, both buffer contains the string Santanu, but the first buffer contains more unused extra bytes. So it is considered as bigger than the second one.

buffer.compare()

buf.compare(target[, targetStart[, targetEnd[, sourceStart[, sourceEnd]]]])

The mechanisam is same as the static Buffer.compare() method. But this one comes with extra option to limit the position in which the comparision will take place.

const buf1 = Buffer.from([1, 2, 3, 4, 5, 6, 7, 8, 9]);
const buf2 = Buffer.from([5, 6, 7, 8, 9, 1, 2, 3, 4]);

console.log(buf1.compare(buf2, 5, 9, 0, 4));
// Prints: 0
console.log(buf1.compare(buf2, 0, 6, 4));
// Prints: -1
console.log(buf1.compare(buf2, 5, 6, 5));
// Prints: 1

buffer.copy()

This method copies the content of first buffer to second buffer.

buf.copy(target[, targetStart[, sourceStart[, sourceEnd]]])

It returns the number of bytes it copied.

// Create two `Buffer` instances.
const buf1 = Buffer.allocUnsafe(26);
const buf2 = Buffer.allocUnsafe(26).fill('!');

for (let i = 0; i < 26; i++) {
  // 97 is the decimal ASCII value for 'a'
  buf1[i] = i + 97;
}

// Copy `buf1` bytes 16 through 19 into `buf2` starting at byte 8 of `buf2`
buf1.copy(buf2, 8, 16, 20);

console.log(buf2.toString('ascii', 0, 25));
// Prints: !!!!!!!!qrst!!!!!!!!!!!!!

buffer.equals()

buffer.equals(otherBuffer)

This method returns true if the buffer is same as otherBuffer. Otherwise it returns false. The two buffers are same in the sense, that they must have exactly same data into their bytes and they must have same length.

const buf1 = Buffer.from('ABC');
const buf2 = Buffer.from('414243', 'hex');
const buf3 = Buffer.from('ABCD');

console.log(buf1.equals(buf2));
// Prints: true
console.log(buf1.equals(buf3));
// Prints: false

buffer.includes()

This method is used to search a piece of data into the buffer. If found it returns true, otherwise it returns false.

buffer.includes(value[, byteOffset][, encoding])

byteOffset is starting index of the buffer from which the search operation will take place. The encoding parameter specifies the format of the provided value, if the value is string.

const buffer = Buffer.from('this is a buffer');

console.log(buffer.includes('this'));
// Prints: true
console.log(buffer.includes('is'));
// Prints: true
console.log(buffer.includes(Buffer.from('a buffer')));
// Prints: true
console.log(buffer.includes(97));
// Prints: true (97 is the decimal ASCII value for 'a')
console.log(buffer.includes(Buffer.from('a buffer example')));
// Prints: false
console.log(buffer.includes(Buffer.from('a buffer example').slice(0, 8)));
// Prints: true
console.log(buffer.includes('this', 4));
// Prints: false

buffer.indexOf()

This method is same as buffer.includes() method. It takes same arguments as buffer.includes(). But this method returns the position of the first occurance of the value. If the value is not found in buffer, then it returns -1.

buf.indexOf(value[, byteOffset][, encoding])

If the value is:

const buf = Buffer.from('this is a buffer');

console.log(buf.indexOf('this'));
// Prints: 0
console.log(buf.indexOf('is'));
// Prints: 2
console.log(buf.indexOf(Buffer.from('a buffer')));
// Prints: 8
console.log(buf.indexOf(97));
// Prints: 8 (97 is the decimal ASCII value for 'a')
console.log(buf.indexOf(Buffer.from('a buffer example')));
// Prints: -1
console.log(buf.indexOf(Buffer.from('a buffer example').slice(0, 8)));
// Prints: 8

buffer.lastIndexOf()

buf.lastIndexOf(value[, byteOffset][, encoding])

Identical to buf.indexOf(), except buf is searched from back to front instead of front to back.

const buf = Buffer.from('this buffer is a buffer');

console.log(buf.lastIndexOf('this'));
// Prints: 0
console.log(buf.lastIndexOf('buffer'));
// Prints: 17
console.log(buf.lastIndexOf(Buffer.from('buffer')));
// Prints: 17
console.log(buf.lastIndexOf(97));
// Prints: 15 (97 is the decimal ASCII value for 'a')
console.log(buf.lastIndexOf(Buffer.from('yolo')));
// Prints: -1
console.log(buf.lastIndexOf('buffer', 5));
// Prints: 5
console.log(buf.lastIndexOf('buffer', 4));
// Prints: -1

buffer.slice()

buf.slice([start[, end]])

This method returns a new buffer.

Returns a new Buffer that references the same memory as the original, but offset and cropped by the start and end indices. Specifying end greater than buf.length will return the same result as that of end equal to buf.length. Modifying the new Buffer slice will modify the memory in the original Buffer because the allocated memory of the two objects overlap.

const buf1 = Buffer.allocUnsafe(26);

for (let i = 0; i < 26; i++) {
  // 97 is the decimal ASCII value for 'a'
  buf1[i] = i + 97;
}

const buf2 = buf1.slice(0, 3);

console.log(buf2.toString('ascii', 0, buf2.length));
// Prints: abc

buf1[0] = 33;

console.log(buf2.toString('ascii', 0, buf2.length));
// Prints: !bc

Specifying negative indexes causes the slice to be generated relative to the end of buf rather than the beginning.

const buf = Buffer.from('buffer');

console.log(buf.slice(-6, -1).toString());
// Prints: buffe
// (Equivalent to buf.slice(0, 5))

console.log(buf.slice(-6, -2).toString());
// Prints: buff
// (Equivalent to buf.slice(0, 4))

console.log(buf.slice(-5, -2).toString());
// Prints: uff
// (Equivalent to buf.slice(1, 4))

buffer.toJSON()

This method returns a JSON representation of the buffer. The method JSON.stringify() implicitily calls this method.

const buf = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5]);
const json = JSON.stringify(buf);

console.log(json);
// Prints: {"type":"Buffer","data":[1,2,3,4,5]}

const copy = JSON.parse(json, (key, value) => {
  return value && value.type === 'Buffer' ?
    Buffer.from(value.data) :
    value;
});

console.log(copy);
// Prints: <Buffer 01 02 03 04 05>

buffer.kMaxLength

The largest size allowed for a single Buffer instance. Note that this is a property on the buffer module returned by require('buffer'), not on the Buffer global or a Buffer instance.

let buffer = require("buffer");
console.log(buffer.kMaxLength); // 2147483647

This property is an alias for buffer.constants.MAX_LENGTH.

Buffer Constants

Note that buffer.constants is a property on the buffer module returned by require('buffer'), not on the Buffer global or a Buffer instance.

buffer.constants.MAX_LENGTH

The largest size allowed for a single Buffer instance.

let buffer = require("buffer");
console.log(buffer.kMaxLength); // 2147483647

buffer.constants.MAX_STRING_LENGTH

The largest length allowed for a single string instance. Represents the largest length that a string primitive can have, counted in UTF-16 code units. This value may depend on the JS engine that is being used

let buffer = require("buffer");
console.log(buffer.constants.MAX_STRING_LENGTH); // 1073741799

Summary

So this is the very basic of Buffer. This tutorial is enough to get started with advance level and application of Node.js buffer. In the next lesson we will go deeper into that module and see what great things we can achieve using this module.