NTM Solutions

Chủ Nhật, 26 tháng 7, 2026

🚀 Node.js LTS (2026) — Bài 10: Streams & Buffer - Xử lý dữ liệu hiệu quả trong Node.js 🌊

"Nếu phải đọc một file 20 GB, bạn sẽ tải toàn bộ vào RAM hay đọc từng phần nhỏ? Câu trả lời chính là Buffer và Stream - hai nền tảng giúp Node.js xử lý dữ liệu cực kỳ hiệu quả."


🎯 Mục tiêu bài học

Sau bài này bạn sẽ:

  • Hiểu Buffer là gì.

  • Hiểu Stream là gì.

  • Biết các loại Stream trong Node.js.

  • Thành thạo Readable Stream và Writable Stream.

  • Biết sử dụng pipe().

  • Hiểu vì sao Stream giúp Node.js xử lý file lớn với hiệu năng cao.


Buffer là gì?

Máy tính chỉ hiểu dữ liệu dưới dạng byte.

Node.js sử dụng Buffer để lưu trữ dữ liệu nhị phân (Binary Data).

Ví dụ:

  • File ảnh

  • Video

  • Âm thanh

  • PDF

  • File ZIP

  • Dữ liệu truyền qua mạng

đều được xử lý bằng Buffer.


Tạo Buffer

const buf =
Buffer.from("Hello");

In ra

console.log(buf);

<Buffer 48 65 6c 6c 6f>

Đây chính là mã ASCII của chuỗi.


Đọc nội dung Buffer

console.log(
buf.toString()
);

Hello

Buffer từ mảng số

const buf =
Buffer.from([
65,
66,
67
]);

console.log(
buf.toString()
);

ABC

Buffer.alloc()

Tạo Buffer có kích thước cố định.

const buf =
Buffer.alloc(8);

console.log(buf);

<Buffer 00 00 00 00 00 00 00 00>

Buffer.byteLength()

Đếm số byte.

console.log(
Buffer.byteLength(
"Node.js"
)
);

7

Ví dụ với Unicode

console.log(
Buffer.byteLength(
"Xin chào"
)
);

Kết quả sẽ lớn hơn số ký tự vì một số ký tự Unicode chiếm nhiều hơn 1 byte.


Stream là gì?

Thay vì:

Đọc toàn bộ file

↓

Đưa vào RAM

↓

Xử lý

Node.js có thể:

Đọc từng phần nhỏ

↓

Xử lý

↓

Đọc tiếp

Đó chính là Stream.


Ví dụ

File

movie.mp4

Dung lượng

20 GB

Nếu đọc bằng:

readFile()

RAM phải chứa toàn bộ file.


Nếu dùng Stream

64 KB

↓

64 KB

↓

64 KB

↓

...

Node chỉ giữ một phần dữ liệu trong bộ nhớ tại mỗi thời điểm.


Lợi ích của Stream

  • Tiết kiệm RAM.

  • Tăng tốc xử lý.

  • Phù hợp file lớn.

  • Có thể xử lý dữ liệu ngay khi nhận được.

  • Được sử dụng trong HTTP, Upload và Download.


Các loại Stream

Node.js có bốn loại Stream.

LoạiÝ nghĩa
ReadableĐọc dữ liệu
WritableGhi dữ liệu
DuplexĐọc và ghi
TransformĐọc, biến đổi rồi ghi

Readable Stream

Đọc file.

import fs from "node:fs";

const stream =
fs.createReadStream(
"data.txt", {
        highWaterMark: 5
    }
);

Lắng nghe dữ liệu

stream.on(
"data",
(chunk)=>{

console.log(chunk);

});

<Buffer ...>

Mỗi lần sẽ nhận một chunk (khối dữ liệu).


Đọc thành chuỗi

stream.setEncoding(
"utf8"
);

stream.on(
"data",
(chunk)=>{

console.log(chunk);

});

Xin

chào

Node.js

Tùy kích thước file, dữ liệu có thể được chia thành nhiều chunk.


Khi đọc xong

stream.on(
"end",
()=>{

console.log(
"Hoàn thành"
);

});

Hoàn thành

Xử lý lỗi

stream.on(
"error",
(err)=>{

console.log(err);

});

Ví dụ:

ENOENT

Writable Stream

Tạo Stream ghi.

import fs from "node:fs";

const stream =

fs.createWriteStream(
"log.txt"
);

Ghi

stream.write(
"Hello\n"
);

stream.write(
"Node.js\n"
);

stream.end();

Nội dung file

Hello

Node.js

end()

Kết thúc Stream.

stream.end();

Sau khi gọi end(), bạn không nên tiếp tục ghi thêm dữ liệu vào Stream đó.


pipe()

Đây là phương pháp phổ biến nhất.

Ví dụ sao chép file (phải có file video.mp4 trong thư mục gốc).

import fs from "node:fs";

const read =

fs.createReadStream(
"video.mp4"
);

const write =

fs.createWriteStream(
"copy.mp4"
);

read.pipe(write);

Sơ đồ

video.mp4

↓

Readable

↓

pipe()

↓

Writable

↓

copy.mp4

Không cần đọc toàn bộ file vào RAM.


highWaterMark

Xác định kích thước mỗi chunk.

const stream =

fs.createReadStream(
"data.txt",
{

highWaterMark:
1024

}
);

1 KB/chunk

Nếu không cấu hình, Node.js sẽ sử dụng giá trị mặc định tùy theo loại Stream.


Ví dụ thực tế

Đếm số byte đã đọc.

let total = 0;

stream.on(
"data",
(chunk)=>{

total +=
chunk.length;

});

stream.on(
"end",
()=>{

console.log(
total
);

});

102400

Stream trong Node.js

Bạn sẽ gặp Stream ở rất nhiều nơi.

HTTP

Express

Upload

Download

Video

Audio

ZIP

Cloud Storage

Database Export

Buffer và Stream khác nhau thế nào?

BufferStream
Lưu dữ liệu trong RAMĐọc/Ghi từng phần
Phù hợp dữ liệu nhỏPhù hợp dữ liệu lớn
Truy cập toàn bộ dữ liệu ngayXử lý theo từng chunk
Có thể tốn nhiều RAMTiết kiệm bộ nhớ

Khi nào dùng Buffer?

Buffer phù hợp khi:

  • Chuỗi nhỏ.

  • Mã hóa dữ liệu.

  • Xử lý Binary.

  • Chuyển đổi Encoding.

  • Làm việc với các gói dữ liệu nhỏ.


Khi nào dùng Stream?

Nên dùng:

  • Upload ảnh.

  • Upload video.

  • Download file.

  • HTTP Server.

  • Sao chép file lớn.

  • Xử lý log.

  • Truyền dữ liệu thời gian thực.


Những lỗi thường gặp

Dùng readFile() với file quá lớn

await fs.readFile(
"movie.mp4"
);

Có thể tiêu tốn rất nhiều RAM hoặc làm ứng dụng phản hồi chậm.

Hãy cân nhắc sử dụng createReadStream() với các tệp lớn.


Quên xử lý lỗi

stream.on(
"error",
(err)=>{

console.log(err);

});

Nếu không lắng nghe sự kiện error, chương trình có thể dừng khi gặp lỗi đọc hoặc ghi file.


Quên gọi end()

stream.write(
"Hello"
);

Nếu không gọi:

stream.end();

Stream ghi có thể chưa đóng đúng cách và dữ liệu có thể chưa được ghi hoàn tất.


Nhầm Buffer với String

console.log(
chunk
);

<Buffer ...>

Muốn đọc dạng văn bản:

chunk.toString();

hoặc:

stream.setEncoding(
"utf8"
);

Bảng tổng hợp

APIÝ nghĩa
Buffer.from()Tạo Buffer
Buffer.alloc()Tạo Buffer rỗng
Buffer.byteLength()Đếm số byte
createReadStream()Đọc Stream
createWriteStream()Ghi Stream
pipe()Nối hai Stream
write()Ghi dữ liệu
end()Kết thúc Stream

Tổng kết

Trong bài học này, bạn đã tìm hiểu hai khái niệm rất quan trọng của Node.js là BufferStream. Buffer dùng để lưu trữ dữ liệu nhị phân trong bộ nhớ, còn Stream cho phép đọc và ghi dữ liệu theo từng phần nhỏ, giúp tiết kiệm RAM và xử lý hiệu quả các tệp có dung lượng lớn.

Đây là nền tảng cho rất nhiều tính năng trong Node.js như HTTP Server, Upload/Download, xử lý video, âm thanh, lưu trữ đám mây và truyền dữ liệu thời gian thực.


Bài tiếp theo

👉 Bài 11 — Callback

Bạn sẽ học:

  • Callback là gì.

  • Callback hoạt động như thế nào.

  • Callback đồng bộ và bất đồng bộ.

  • Callback Hell là gì.

  • Vì sao Promise và Async/Await ra đời để giải quyết những hạn chế của Callback.

x1
quay về MỤC LỤC

Không có nhận xét nào:

Đăng nhận xét

Facebook Youtube RSS