Mojibake (Lỗi hiển thị ký tự)
Hiện tượng ký tự gốc bị hiển thị thành ký hiệu vô nghĩa hoặc ký tự khác do sự không khớp giữa mã hóa và giải mã dữ liệu văn bản.
Mojibake (文字化け) là hiện tượng xảy ra khi mã hóa ký tự dùng để ghi dữ liệu văn bản khác với mã hóa dùng để đọc. Ví dụ, khi mở một tệp tiếng Nhật được lưu bằng UTF-8 dưới dạng Shift_JIS, chuỗi "こんにちは" sẽ biến thành "縺薙s縺ォ縺。縺ッ" - một dãy ký tự hoàn toàn vô nghĩa. Ngược lại, mở tệp Shift_JIS bằng UTF-8 sẽ hiển thị hàng loạt ký tự thay thế "�" hoặc các chữ Hán hoàn toàn khác.
- 1. Bên ghi lưu văn bản bằng UTF-8 Năm ký tự "こんにちは" mỗi ký tự chiếm 3 byte trong UTF-8, nên tệp lưu lại một dãy tổng cộng 15 byte.
- thỏa thuận "đây là UTF-8" không đến được bên đọc
- 2. Bên đọc cắt dãy byte theo quy tắc Shift_JIS Cùng 15 byte đó được chia lại thành từng khối 1 đến 2 byte theo Shift_JIS, nên ranh giới ký tự khác hoàn toàn so với 5 ký tự ban đầu.
- một bảng mã khác quyết định ký tự được hiển thị
- 3. Màn hình hiện ra "縺薙s縺ォ縺。縺ッ" Chỉ phần hiển thị thay đổi; 5 ký tự gốc không bị thay bằng dữ liệu khác. Vấn đề nằm ở mã hóa mà bên đọc đang dùng.
| Mã hóa khi lưu | Mã hóa khi đọc | Chuỗi hiện trên màn hình |
|---|---|---|
| UTF-8 | UTF-8 (khớp) | こんにちは |
| UTF-8 | Shift_JIS | 縺薙s縺ォ縺。縺ッ |
| UTF-8 | Latin-1 | Hiện các ký hiệu không đọc được, 5 ký tự bị đếm thành 15 ký tự |
| Shift_JIS | UTF-8 | Hàng loạt ký tự thay thế �, hoặc các chữ Hán hoàn toàn khác |
Trong bốn tổ hợp, chỉ dòng có mã hóa khi lưu trùng với mã hóa khi đọc là hiển thị đúng. Hãy kiểm tra điều đó trước khi tin vào kết quả đếm ký tự.
Có ba kịch bản điển hình gây ra mojibake. Thứ nhất, mã hóa khi lưu tệp khác với mã hóa khi đọc. Thứ hai, cài đặt kết nối cơ sở dữ liệu không khớp với bộ ký tự của bảng. Thứ ba, charset được chỉ định trong header HTTP Content-Type khác với mã hóa thực tế của tệp HTML. Cả ba trường hợp đều có cùng bản chất: "thỏa thuận giữa bên ghi và bên đọc không khớp nhau."
Nhìn từ góc độ lịch sử, mojibake gắn liền sâu sắc với văn hóa máy tính Nhật Bản. Trong thập niên 1980-1990, ba bảng mã tiếng Nhật chính - JIS, Shift_JIS và EUC-JP - tồn tại song song, khiến mojibake xảy ra thường xuyên trong email và trang web. Đặc biệt với email, dù ISO-2022-JP được coi là chuẩn, mỗi ứng dụng email lại sử dụng mã hóa khác nhau, gây ra lỗi hiển thị ở phía người nhận. Đối với tiếng Việt, vấn đề tương tự từng xảy ra với các bảng mã TCVN 3, VNI và VISCII trước khi Unicode được phổ biến rộng rãi.
Hiện nay, UTF-8 đã trở thành chuẩn thực tế của web và tần suất mojibake đã giảm đáng kể. Theo khảo sát tình hình sử dụng của W3Techs, tính đến ngày 5 tháng 9 năm 2026, 99,0% website sử dụng UTF-8. Tuy nhiên, mojibake chưa hoàn toàn biến mất: kết nối với hệ thống cũ, trao đổi tệp CSV (Excel yêu cầu UTF-8 có BOM), di chuyển cơ sở dữ liệu cũ vẫn là những tình huống phổ biến.
Các biện pháp phòng tránh mojibake trong thực tế khá rõ ràng. Thống nhất tệp ở định dạng UTF-8 (không BOM). Sử dụng bộ ký tự utf8mb4 cho cơ sở dữ liệu. Chỉ định rõ Content-Type: text/html; charset=UTF-8 trong phản hồi HTTP. Xuất CSV dạng UTF-8 có BOM khi cần mở bằng Excel. Tuân thủ nhất quán những nguyên tắc này giúp bên ghi và bên đọc dùng cùng một mã hóa, và đó chính là điều kiện để tránh mojibake.
Từ góc độ đếm ký tự, văn bản bị mojibake có sự chênh lệch lớn giữa số ký tự hiển thị và số byte thực tế. Ví dụ, khi văn bản tiếng Nhật UTF-8 bị hiểu nhầm là Latin-1, mỗi ký tự sẽ "phình" thành 3 ký tự, khiến kết quả đếm gấp gần 3 lần so với thực tế. Điều kiện tiên quyết để đếm ký tự chính xác là mã hóa của văn bản phải được nhận diện đúng.