CodeGym /Các khóa học /C# SELF /Định dạng file: Văn bản và Nhị phân

Định dạng file: Văn bản và Nhị phân

C# SELF
Mức độ , Bài học
Có sẵn

1. File văn bản

Nhớ nhé: máy tính lưu trữ mọi thứ, thật sự là mọi thứ, dưới dạng 0 và 1 (hoặc, nếu không ngại từ chuyên môn — là chuỗi byte). Nhưng nếu bạn đưa cùng một file cho hai chương trình khác nhau, chưa chắc chúng sẽ xử lý giống nhau đâu. Ví dụ, một chương trình sẽ thấy đó là văn bản bình thường, còn chương trình khác lại thấy toàn "byte lỗi". Tất cả là do định dạng file — tức là, cách các byte này được diễn giải. Định dạng mô tả cấu trúc dữ liệu bên trong, quy tắc đọc và mã hóa. Nếu không biết định dạng, chương trình có thể không hiểu file đó chứa gì luôn.

File văn bản — là file mà dữ liệu được lưu dưới dạng văn bản thông thường với một mã hóa nào đó (thường là UTF-8 hoặc, hardcore hơn thì ASCII). Nội dung file này bạn có thể mở bằng bất kỳ trình soạn thảo văn bản nào (ví dụ Notepad hoặc VS Code) và đọc ngay — nó là chuỗi ký tự, không phải mấy byte điều khiển bí ẩn hay cấu trúc nhị phân khó hiểu.

Ví dụ điển hình

  • *.txt — file văn bản thông thường, ví dụ "to-do.txt" hoặc "best-books.txt".
  • *.csv — file mà dữ liệu được phân tách bằng dấu phẩy hoặc chấm phẩy (rất tiện cho bảng).
  • *.json — file để trao đổi dữ liệu có cấu trúc (ví dụ danh sách sách).
  • *.xml,*.html — để lưu trữ và truyền dữ liệu có cấu trúc.

Ví dụ file CSV


Dune;Frank Herbert;1965
1984;George Orwell;1949
Master i Margarita;Mikhail Bulgakov;1966
Ví dụ nội dung books.txt (định dạng CSV)

Mỗi dòng — là một bản ghi riêng biệt (ví dụ, một cuốn sách). Các giá trị trong dòng được phân tách bằng dấu chấm phẩy, làm cho file này là ví dụ của CSV (Comma-Separated Values). Comma là dấu phẩy, nhưng ở đây lại dùng dấu phân cách khác (;). Những ký tự mà bạn nhìn thấy — chính là các byte mà chương trình cũng đọc được, miễn là nó biết cách diễn giải định dạng văn bản và mã hóa file.

Chương trình làm việc với file văn bản như thế nào

Chỉ cần mở file "dưới dạng văn bản", là có thể đọc từng dòng. Ví dụ (sẽ hữu ích cho bạn trong các bài sau):


// Đọc từng dòng từ file (chi tiết sẽ học sau)
string[] lines = File.ReadAllLines("books.txt");
foreach (string line in lines)
{
    Console.WriteLine(line);
}

Ưu điểm của file văn bản

  • Dễ đọc với con người (human-readable).
  • Dễ chỉnh sửa bằng tay (ngay cả với Notepad đơn giản nhất).
  • Rất phù hợp để debug và trao đổi giữa các hệ thống khác nhau.
  • Dễ chuyển giữa các nền tảng (Windows, Linux, Mac).

Nhược điểm của file văn bản

  • Không có cấu trúc chặt chẽ (txt), lỗi định dạng rất dễ xảy ra.
  • Chiếm nhiều dung lượng hơn (ví dụ số 12345 = 5 byte, còn nhị phân chỉ 4).
  • Dữ liệu phức tạp (ví dụ ảnh, audio) truyền qua văn bản rất bất tiện hoặc không thể.
  • Hiệu năng: chậm hơn khi dữ liệu lớn.

Lưu ý hay ho

  • Các nền tảng khác nhau hiểu "kết thúc dòng" khác nhau: Windows — \r\n, Unix — \n.
  • Mã hóa có thể khác nhau (UTF-8, UTF-16, ANSI v.v.), nên file ghi ở hệ này có thể hiện ra "ký tự Trung Quốc" ở hệ khác (thực ra là do diễn giải byte sai).

2. File nhị phân

File nhị phân — là file mà bên trong không lưu ký tự, mà là các byte bất kỳ. Chúng có thể là bất cứ thứ gì: số, cấu trúc, ảnh, nhạc, thậm chí mã máy. Thử mở .exe bằng Notepad xem — sẽ thấy toàn ký tự loạn xạ!

Ví dụ điển hình

  • *.exe, *.dll — file thực thi và thư viện.
  • *.jpg, *.png, *.gif— ảnh.
  • *.mp3, *.wav— file audio.
  • *.dat — file dữ liệu người dùng bất kỳ.
  • Định dạng riêng của ứng dụng (*.docx, *.xlsx v.v.) — gần như luôn là nhị phân.

File nhị phân được tổ chức như thế nào?

Byte nối byte, chương trình ghi và đọc dữ liệu theo đúng định dạng nó muốn. Ví dụ, số kiểu int sẽ chiếm 4 byte (32 bit), còn chuỗi — thường là độ dài + các byte ký tự theo mã hóa nhất định.

Trong file văn bản, số 12345 — là các byte tương ứng với ký tự '1', '2', '3', '4', '5':

Ký tự Mã UTF-8
1 49
2 50
3 51
4 52
5 53

Trong file nhị phân int 12345 (kiểu little-endian) sẽ như sau:

Vị trí Byte (hex) Giá trị
0 0x39 57
1 0x30 48
2 0x00 0
3 0x00 0

(Nói cách khác: 12345 = 0x00003039.)

Thử ghi cùng một số ở dạng văn bản và nhị phân — rồi so sánh kích thước file. File nhị phân sẽ nhỏ hơn chút.

Chương trình làm việc với file nhị phân như thế nào

Dùng các stream đặc biệt (ví dụ BinaryReader, BinaryWriter). Khác với file văn bản, bạn phải biết chính xác cấu trúc, nếu không sẽ không đọc được dữ liệu.


// Ví dụ ghi số vào file nhị phân
var writer = new BinaryWriter(File.Open("books.bin", FileMode.Create));

// Ví dụ, ghi chuỗi: số ký tự (int), rồi các byte
string title = "Dune";
writer.Write(title.Length); // Ghi độ dài (int)
writer.Write(title); // Ghi chuỗi (sẽ là UTF-8)
writer.Write(1965); // Ghi năm (int)

writer.Close(); // đóng stream

Đây chỉ là ví dụ thôi. Chi tiết về file nhị phân mình sẽ nói kỹ hơn ở các bài sau.

Ưu điểm của file nhị phân

  • Gọn nhẹ: chiếm ít dung lượng hơn.
  • Đọc/ghi nhanh hơn (đặc biệt với dữ liệu lớn).
  • Có thể lưu cấu trúc phức tạp: mảng, object lồng nhau v.v.

Nhược điểm của file nhị phân

  • Không đọc được bằng mắt thường (human-unreadable).
  • Nếu cấu trúc file thay đổi, dữ liệu cũ có thể mất hoặc "hỏng".
  • Luôn cần hướng dẫn chính xác để phân tích nội dung.

3. Chọn định dạng nào?

File văn bản vs File nhị phân

Tiêu chí File văn bản File nhị phân
Dễ đọc với người Không
Kích thước Lớn hơn Nhỏ hơn
Đa năng Cao (bất kỳ editor nào) Chỉ chương trình đặc biệt
Tốc độ Chậm hơn Nhanh hơn
Định dạng chặt chẽ Không Có, phải tuân thủ
Lưu cấu trúc Khó Dễ
Rủi ro hỏng dữ liệu Thấp (dễ sửa) Cao (lỗi nhỏ là không đọc được)

Tiêu chí chọn lựa

  • Cần dữ liệu dễ đọc, dễ sửa, dễ debug? — Dùng file văn bản (ví dụ .txt, .csv, .json).
  • Dữ liệu phức tạp, cần tối ưu kích thước và tốc độ? — Chọn nhị phân.
  • Cần trao đổi dữ liệu giữa nhiều nền tảng? — Văn bản sẽ tiện hơn, nhưng mã hóa nên là chuẩn (UTF-8).
  • Ứng dụng đọc/ghi nhiều dữ liệu, định dạng phải chặt? — Chọn nhị phân.

Trong ứng dụng console "Danh sách sách" của tụi mình giai đoạn đầu dùng file văn bản (.csv hoặc .txt) là quá ổn. Sau này, khi cấu trúc phức tạp hơn hoặc muốn tăng tốc độ load, có thể học file nhị phân hoặc chuyển sang JSON/XML.

4. Một số lưu ý hay ho

File văn bản và nhị phân gặp ở đâu trong đời?

File văn bản:

  • Cài đặt chương trình (thường là .ini hoặc .json).
  • Script, log, ghi chú.
  • File import/export (dữ liệu trao đổi giữa app).

File nhị phân:

  • Chương trình, game, thư viện (không ai tự ý mở được đâu).
  • Cơ sở dữ liệu lớn và archive (ví dụ .mdb, .zip).
  • Media: nhạc, ảnh, video.

Đọc toàn bộ file một lần (dạng văn bản):


string allText = File.ReadAllText("books.txt");
// Giờ allText là một chuỗi to đùng chứa toàn bộ nội dung

Theo từng dòng (tối ưu cho danh sách):


string[] lines = File.ReadAllLines("books.txt");
foreach (string line in lines)
{
    // Có thể tách dòng thành các phần
    string[] parts = line.Split(';');
    // parts[0] — tên sách, parts[1] — tác giả, parts[2] — năm
}

Đọc nhị phân — phải đúng cấu trúc


var reader = new BinaryReader(File.Open("books.bin", FileMode.Open));

int count = reader.ReadInt32(); // Số lượng sách
for (int i = 0; i < count; i++)
{
    string title = reader.ReadString();
    string author = reader.ReadString();
    int year = reader.ReadInt32();
    // Giờ có thể khôi phục bản ghi!
}

reader.Close();

5. Ví dụ thực tế: tạo file lưu sách

Lưu dữ liệu vào file văn bản

Mỗi cuốn sách sẽ lưu trên một dòng theo định dạng:
tên sách;tác giả;năm xuất bản đầu tiên


// Danh sách sách muốn lưu
var books = new List<(string Title, string Author, int Year)>
{
    ("Dune", "Frank Herbert", 1965),
    ("1984", "George Orwell", 1949),
    ("Master i Margarita", "Mikhail Bulgakov", 1966)
};

// Lưu vào file văn bản
var writer = new StreamWriter("books.txt");
foreach (var book in books)
    writer.WriteLine($"{book.Title};{book.Author};{book.Year}");

writer.Close();

Bạn có thể mở books.txt bằng Notepad và xem toàn bộ dữ liệu.

Lưu dữ liệu vào file nhị phân

Giờ thử làm tương tự, nhưng gọn hơn (dù không đọc được bằng mắt thường):


var writer = new BinaryWriter(File.Open("books.bin", FileMode.Create));

writer.Write(books.Count); // Ghi số lượng sách
foreach (var book in books)
{
    writer.Write(book.Title); // Chuỗi - lưu: độ dài + byte
    writer.Write(book.Author); // Chuỗi
    writer.Write(book.Year); // Năm (int)
}

writer.Close();

Nếu thử mở books.bin bằng editor văn bản, bạn sẽ thấy toàn ký tự loạn xạ. Bình thường thôi. File nhị phân không dành cho con người đọc — chỉ chương trình biết đúng cách ghi/đọc mới xử lý được.

6. Lỗi thường gặp khi làm việc với định dạng

Nếu thử đọc file nhị phân như file văn bản, bạn sẽ nhận được "cháo" ký tự hoặc lỗi luôn. Tương tự, nếu mở file văn bản như nhị phân và mong chờ cấu trúc chặt chẽ — sẽ có vấn đề.

Lỗi phổ biến nhất: không khớp cấu trúc dữ liệu và thứ tự đọc/ghi. Ví dụ, ghi năm trước, tên sau, nhưng đọc ngược lại — sẽ ra dữ liệu sai. Luôn tuân thủ đúng thứ tự thao tác nhé!

Rất nhiều lập trình viên "soi" file văn bản để kiểm tra logic lưu/đọc — đó là lý do file văn bản rất tiện cho giai đoạn đầu. File nhị phân thì hợp cho các kịch bản nâng cao, hoặc khi muốn ẩn chi tiết lưu trữ khỏi người dùng.

Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION