Node.js - Buffers: Hướng dẫn cho người mới bắt đầu

Xin chào các pháp sư Node.js tương lai! Tôi rất vui mừng được làm hướng dẫn viên cho bạn trong hành trình thú vị vào thế giới của Node.js Buffers. Là người đã dạy lập trình trong nhiều năm, tôi có thể nói rằng Buffers là những người hùng vô danh trong việc xử lý dữ liệu trong Node.js. Chúng có thể看起来有点 kỳ bí ban đầu, nhưng đến cuối bài hướng dẫn này, bạn sẽ sử dụng chúng như một chuyên gia!

Node.js - Buffers

Buffers là gì?

Trước khi chúng ta đi vào chi tiết, hãy bắt đầu với những điều cơ bản. Hãy tưởng tượng bạn đang cố gắng di chuyển một ngọn núi cát. Bạn có thể cố gắng di chuyển nó từng hạt, nhưng điều đó sẽ mất rất nhiều thời gian! Thay vào đó, bạn sẽ sử dụng một chậu. Trong thế giới Node.js, Buffers giống như những chậu đó - chúng giúp chúng ta xử lý và di chuyển dữ liệu nhị phân một cách hiệu quả.

Buffers là các khối bộ nhớ có kích thước cố định, được phân bổ bên ngoài engine V8 của JavaScript. Chúng đặc biệt hữu ích khi xử lý các thao tác tệp, giao thức mạng hoặc bất kỳ tình huống nào bạn cần làm việc với các luồng dữ liệu nhị phân.

Tạo một Buffer

Hãy bắt đầu bằng cách tạo Buffer đầu tiên của chúng ta:

const buf1 = Buffer.alloc(10);
console.log(buf1);

Khi bạn chạy đoạn mã này, bạn sẽ thấy điều gì đó như sau:

<Buffer 00 00 00 00 00 00 00 00 00 00>

Điều gì vừa xảy ra? Chúng ta đã tạo một Buffer có kích thước 10 byte, và tất cả các byte đều được khởi tạo bằng zero. Nó giống như chúng ta vừa nhận được một chậu mới, sạch sẽ và trống rỗng, sẵn sàng để chứa dữ liệu cát của chúng ta!

Bây giờ, hãy tạo một Buffer với một nội dung ban đầu:

const buf2 = Buffer.from('Hello, Node.js!');
console.log(buf2);

Kết quả đầu ra:

<Buffer 48 65 6c 6c 6f 2c 20 4e 6f 64 65 2e 6a 73 21>

Ở đây, chúng ta đã tạo một Buffer từ một chuỗi. Mỗi số bạn thấy đại diện cho mã ASCII của mỗi ký tự trong chuỗi của chúng ta. Đúng là cool, phải không?

Phương thức tĩnh

Node.js cung cấp nhiều phương thức tĩnh để làm việc với Buffers. Hãy cùng khám phá một số phương thức phổ biến nhất:

Buffer.alloc()

Chúng ta đã thấy phương thức này trong hành động. Nó tạo một Buffer mới với kích thước được chỉ định, với tất cả các byte được khởi tạo bằng zero.

const buf3 = Buffer.alloc(5);
console.log(buf3); // <Buffer 00 00 00 00 00>

Buffer.from()

Phương thức này tạo một Buffer mới từ một mảng, một Buffer khác hoặc một chuỗi.

const buf4 = Buffer.from([1, 2, 3, 4, 5]);
console.log(buf4); // <Buffer 01 02 03 04 05>

const buf5 = Buffer.from('Hello');
console.log(buf5); // <Buffer 48 65 6c 6c 6f>

Buffer.concat()

Phương thức này ghép nối một danh sách các Buffer.

const buf6 = Buffer.from('Hello');
const buf7 = Buffer.from(' World');
const buf8 = Buffer.concat([buf6, buf7]);
console.log(buf8.toString()); // Hello World

Dưới đây là bảng tóm tắt các phương thức tĩnh này:

Phương thức Mô tả Ví dụ
Buffer.alloc() Tạo một Buffer có kích thước được chỉ định Buffer.alloc(10)
Buffer.from() Tạo một Buffer từ mảng, Buffer, hoặc chuỗi Buffer.from('Hello')
Buffer.concat() Ghép nối một danh sách các Buffer Buffer.concat([buf1, buf2])

Tham chiếu phương thức

Bây giờ chúng ta đã tạo ra các Buffer của mình, hãy xem xét một số phương thức chúng ta có thể sử dụng để làm việc với chúng.

buf.toString()

Phương thức này giải mã một Buffer thành một chuỗi theo mã ký tự được chỉ định.

const buf9 = Buffer.from('Hello, Buffer!');
console.log(buf9.toString()); // Hello, Buffer!
console.log(buf9.toString('hex')); // 48656c6c6f2c2042756666657221

buf.write()

Phương thức này ghi một chuỗi vào Buffer.

const buf10 = Buffer.alloc(20);
buf10.write('Hello');
console.log(buf10.toString()); // Hello

buf.slice()

Phương thức này trả về một Buffer mới tham chiếu cùng bộ nhớ với原件, nhưng sử dụng các chỉ số bắt đầu và kết thúc bạn chỉ định.

const buf11 = Buffer.from('Hello, Buffer!');
const slicedBuf = buf11.slice(0, 5);
console.log(slicedBuf.toString()); // Hello

Dưới đây là bảng tóm tắt các phương thức này:

Phương thức Mô tả Ví dụ
buf.toString() Giải mã Buffer thành chuỗi buf.toString()
buf.write() Ghi chuỗi vào Buffer buf.write('Hello')
buf.slice() Trả về Buffer mới tham chiếu cùng bộ nhớ buf.slice(0, 5)

Phương thức lớp

Cuối cùng, hãy xem xét một số phương thức lớp có thể đặc biệt hữu ích khi làm việc với Buffers.

Buffer.isBuffer()

Phương thức này kiểm tra xem một đối tượng có phải là Buffer hay không.

const buf12 = Buffer.from('Hello');
console.log(Buffer.isBuffer(buf12)); // true
console.log(Buffer.isBuffer('Not a buffer')); // false

Buffer.byteLength()

Phương thức này trả về số byte trong một chuỗi hoặc Buffer.

console.log(Buffer.byteLength('Hello')); // 5
console.log(Buffer.byteLength('?')); // 4 (vì biểu tượng này là 4 byte)

Dưới đây là bảng tóm tắt các phương thức này:

Phương thức Mô tả Ví dụ
Buffer.isBuffer() Kiểm tra xem đối tượng có phải là Buffer hay không Buffer.isBuffer(obj)
Buffer.byteLength() Trả về số byte của chuỗi hoặc Buffer Buffer.byteLength('Hello')

Và thế là bạn đã có tất cả, các bạn! Chúng ta đã cùng nhau hành trình qua vùng đất của Node.js Buffers, từ việc tạo chúng đến việc điều chỉnh nội dung của chúng. Nhớ rằng, thực hành là cách tốt nhất để hiểu. Vì vậy, đừng ngại thử nghiệm với các phương thức này và xem bạn có thể tạo ra điều gì.

Trong những năm dạy học của tôi, tôi đã phát hiện ra rằng cách tốt nhất để thực sự hiểu Buffers là sử dụng chúng trong các dự án thực tế. Hãy thử đọc một tệp vào Buffer, hoặc gửi dữ liệu Buffer qua mạng. Càng sử dụng nhiều, chúng sẽ càng trở nên tự nhiên hơn.

Trước khi tôi kết thúc, đây là một câu đùa về Buffer cho bạn: Tại sao Buffer lại qua đường? Để đến byte khác! (Tôi biết, tôi biết, tôi nên stick với lập trình...)

Chúc các bạn lập trình vui vẻ, và hy vọng Buffers của bạn luôn đầy chính xác dữ liệu bạn cần!

Credits: Image by storyset