- UTF-8 mã hóa các điểm Unicode trong 1–4 byte, tương thích với ASCII và hợp lệ với mọi ngôn ngữ.
- Tự đồng bộ hóa và xác thực: Các mẫu 0/110/1110/11110 ngăn ngừa sự chồng chéo và giúp phát hiện lỗi dễ dàng hơn.
- Web và hệ thống: bộ ký tự meta, hỗ trợ rộng rãi và dễ dàng chuyển đổi trên Windows/macOS/Linux.
Nếu bạn đang đọc bài viết này hôm nay mà không thấy bất kỳ ký hiệu lạ nào, đó là nhờ UTF-8 . Mã hóa này cho phép các chữ cái, dấu nhấn, ký hiệu kỹ thuật và thậm chí cả biểu tượng cảm xúc được hiển thị giống nhau trên mọi trình duyệt, hệ điều hành hoặc ứng dụng email hiện đại. Đây là tiêu chuẩn được sử dụng rộng rãi nhất trên web và là nền tảng của giao tiếp kỹ thuật số như chúng ta biết.
Khi một thiết bị hiển thị văn bản, thực chất nó đang xử lý các con số . Những con số này là các điểm mã được định nghĩa bởi tiêu chuẩn Unicode , và để chuyển đổi chúng thành các byte truyền qua mạng hoặc được lưu vào tệp, chúng ta thực hiện một phép biến đổi: UTF-8 . Trong những dòng tiếp theo, bạn sẽ hiểu UTF-8 là gì, cách thức hoạt động, tại sao nó trở thành tiêu chuẩn, những ưu điểm và hạn chế của nó, và cách tránh các lỗi thường gặp.
UTF-8 là gì?
UTF-8 (Định dạng chuyển đổi Unicode 8 bit) là một phương pháp chuyển đổi các điểm mã Unicode thành chuỗi byte . Đặc điểm chính của nó là sử dụng độ dài biến đổi : một số ký tự chiếm 1 byte, trong khi những ký tự khác yêu cầu 2, 3 hoặc 4 byte. Điều này cho phép tạo ra các văn bản nhỏ gọn với các ký tự Latinh đơn giản , nhưng nó cũng có thể biểu diễn bất kỳ ký tự nào từ kho ký tự Unicode.
Nó hoàn toàn tương thích với ASCII : 128 ký tự đầu tiên (U+0000 đến U+007F) được mã hóa bằng một byte duy nhất giống hệt với ASCII 7 bit. Điều này đã tạo điều kiện thuận lợi cho quá trình chuyển đổi từ các hệ thống cũ hơn và giải thích phần lớn sự thành công của nó trên Internet, trong email và trong các giao thức IETF.
UTF-8 nổi bật nhờ tính mạnh mẽ : nó tích hợp các bit đồng bộ hóa cho phép xác định chính xác điểm bắt đầu của mỗi ký hiệu. Thuộc tính tự đồng bộ hóa này giúp dễ dàng phát hiện xem một chuỗi có "trông" giống UTF-8 hay không , điều này rất hữu ích trong các công cụ và trình phân tích cú pháp.
Unicode: Nền tảng của mọi thứ
Unicode là tiêu chuẩn toàn cầu gán một mã số duy nhất cho mỗi ký tự , bất kể ngôn ngữ, nền tảng hay ứng dụng nào. Mã số này được gọi là điểm mã và thường được viết dưới dạng thập lục phân theo định dạng U+XXXX (hoặc nhiều chữ số hơn nếu cần).
Ví dụ: Chữ in hoa “A” là U+0041Trong HTML chúng ta cũng có thể gọi nó là A. Máy tính của bạn không "nghĩ" A là một chữ cái, mà là số 65và sau đó mã hóa (như UTF-8) quyết định cách biểu diễn số đó theo byte.
Nếu bạn muốn xem Unicode được chuyển đổi thành các ký tự như thế nào trên máy tính của mình , trên Windows, bạn có thể giữ phím Alt và nhập mã số thập phân trên bàn phím số: ví dụ, Alt+65 sẽ cho ra ký tự “A” (xem danh sách đầy đủ các mã Alt ). Đây là một phím tắt kinh điển cho thấy các mã này nằm bên dưới các ký tự mà bạn nhìn thấy.
Một chút lịch sử: UTF-8 ra đời như thế nào
UTF-8 được Ken Thompson phát minh dưới sự hướng dẫn của Rob Pike vào ngày 2 tháng 9 năm 1992. Họ đã triển khai nó trong hệ điều hành Plan 9 của Bell Labs và chính thức giới thiệu tại USENIX (San Diego, tháng 1 năm 1993) . Trong quá trình chuẩn hóa, được tài trợ bởi Nhóm Quốc tế hóa Chung X/Open (XOJIG) , nó được biết đến với các tên gọi như FSS/UTF và UTF-2 trước khi được hợp nhất thành UTF-8.
Thiết kế này đã giải quyết được những vấn đề thực tiễn gây khó khăn cho các nỗ lực mã hóa phổ quát trước đây: khả năng tương thích ASCII, tự đồng bộ hóa, không có byte chồng chéo và dễ dàng phát hiện lỗi. Sự cân bằng này đã khiến nó trở thành tiêu chuẩn thực tế của web.
UTF-8 hoạt động như thế nào?
UTF-8 nhóm các ký tự theo số byte cần thiết để mã hóa chúng . Số byte phụ thuộc hoàn toàn vào điểm mã Unicode và tuân theo các mẫu bit cho biết độ dài của chuỗi.
- 1 byte (U+0000 đến U+007F): Ký tự ASCII. Định dạng:
0xxxxxxx. Bit quan trọng nhất là 0, đảm bảo khả năng tương thích trực tiếp với ASCII. - 2 byte (U+0080 đến U+07FF): Định dạng
110yyyyy 10xxxxxx. Nó được sử dụng cho hầu hết các bảng chữ cái châu Âu có dấu phụ và các chữ cái khác như tiếng Hy Lạp, tiếng Kirin, tiếng Do Thái hoặc tiếng Ả Rập.. - 3 byte (U+0800 đến U+FFFF): Định dạng
1110zzzz 10yyyyyy 10xxxxxx. Bao gồm gói cơ bản đa ngôn ngữ (BMP), với CJK (tiếng Trung, tiếng Nhật, tiếng Hàn), các ký hiệu kỹ thuật và các ký tự được sử dụng phổ biến nhất. - 4 byte (U+10000 đến U+10FFFF): Định dạng
11110uuu 10uuzzzz 10yyyyyy 10xxxxxx. Biểu diễn các mặt phẳng bổ sung: các ký hiệu toán học nâng cao, các tác phẩm lịch sử, các ký hiệu tượng hình ít phổ biến hơn, v.v.
Điểm mấu chốt của việc tự đồng bộ hóa nằm ở các bit tiêu đề : 0 cho ASCII; 110 cho hai byte; 1110 cho ba byte; 11110 cho bốn byte. Các byte tiếp theo luôn bắt đầu bằng 10. Nhờ đó, một byte tiếp theo không bao giờ có thể xuất hiện như một byte bắt đầu , và một chuỗi hợp lệ không bao giờ có thể là một chuỗi con của một chuỗi dài hơn (nguyên tắc không chồng chéo).
Sự tương đương với UTF-16 và các cặp thay thế
UTF-16 biểu diễn các điểm mã BMP với đơn vị là 16 bit và các điểm trên U+FFFF với cặp thay thế trong phạm vi D800–DFFF. Thay vào đó UTF-8 luôn mã hóa các điểm mã thực, không phải đơn vị UTF-16, giúp tránh nhầm lẫn với các đơn vị thay thế.
Trong quá khứ, một số bản thảo cho phép sử dụng 5 hoặc 6 byte trong UTF-8 để bao phủ phạm vi rộng hơn, nhưng Unicode và RFC 3629 giới hạn UTF-8 ở mức tối đa 4 byte . ISO/IEC đã xem xét các tùy chọn rộng hơn, nhưng những tùy chọn này không phải là một phần của tiêu chuẩn hiện hành.
Ví dụ thực tế: ñ
Ký tự “ñ” có mã điểm U+00F1, nằm trong phạm vi hai byte. Theo mẫu, nó được mã hóa thành 110xxxxx 10xxxxxx. Biểu diễn UTF-8 của nó là 0xC3 0xB1Giải mã là quá trình ngược lại: đọc các bit hữu ích và tái tạo lại điểm mã gốc.
Ưu điểm và hạn chế của UTF-8
Ưu điểm chính :
- Hỗ trợ ASCII: Văn bản ASCII có giá trị trong UTF-8 mà không cần thay đổi.
- phổ cập: có thể biểu diễn bất kỳ ký tự Unicode nào, bao gồm các ký hiệu kỹ thuật và biểu tượng cảm xúc.
- Hiệu quả trong các văn bản tiếng Latin: khi sử dụng 1 byte cho ASCII, tiết kiệm không gian so với UTF-16 trong nhiều ngôn ngữ phương Tây.
- Tự đồng bộ hóa và phát hiện: các mẫu bit cho phép phát hiện sự khởi đầu của nhân vật và xác thực trình tự một cách dễ dàng.
Những hạn chế và sự đánh đổi :
- Văn bản CJK chiếm nhiều không gian hơn văn bản UTF-16, trong đó nhiều ký tự đó nằm gọn trong 2 byte cố định.
- Chi phí tính toán: có độ dài thay đổi, một số thao tác (ví dụ: "đi đến ký tự n") yêu cầu phải trải qua từ đầuvà một số tác vụ nhất định có thể nhanh hơn trong UTF-16/UTF-32.
BOM (Dấu thứ tự byte) trong UTF-8
UTF-8 không cần BOM vì thứ tự byte không làm thay đổi ý nghĩa của các giá trị (đơn vị nhỏ nhất là byte). Tuy nhiên, Có một BOM tùy chọn, ký tự U+FEFF được mã hóa thành EF BB BF ở đầu tệp hoặc luồng, có thể được sử dụng để chỉ ra "đây là Unicode/UTF-8".
Các thực tiễn tốt nhất : Nếu nó xuất hiện ở đầu chuỗi, một số hệ thống chấp nhận nó và một số hệ thống khác xử lý nó theo nghĩa đen. Trong các chuỗi ghép, nên loại bỏ các BOM trung gian . Việc bao gồm nó không bắt buộc, và tính hữu ích của nó trong UTF-8 bị hạn chế so với UTF-16/UTF-32, nơi nó đánh dấu thứ tự byte.
Lỗi mã hóa thông thường và cách xử lý chúng
Bộ giải mã UTF-8 mạnh mẽ phải từ chối các chuỗi ký tự không đúng định dạng hoặc thay thế chúng bằng U+FFFD (KÝ TỰ THAY THẾ) hoặc báo lỗi. Các lỗi phổ biến nhất là:
- Trình tự bị cắt cụt: một byte dẫn đầu nhiều byte không có đủ sự tiếp nối.
- Các byte tiếp tục lỏng lẻo: xuất hiện
10xxxxxxkhông có byte dẫn hợp lệ. - Quá dài: mã hóa với nhiều byte hơn mức cần thiết; ví dụ, cố gắng mã hóa ASCII với 2 byte (
0xC0y0xC1không hợp lệ). - Độ dài bị cấm: bắt đầu gợi ý 5 hoặc 6 byte (
0xF8–0xFDkhông hợp lệ theo chuẩn UTF-8). - Giá trị nằm ngoài phạm vi Unicode: không được hỗ trợ trên U+10FFFF; một số giá trị nhất định (
0xF5–0xF7như sự khởi đầu) là không hợp lệ. - Cặp thay thế UTF-16:
D800–DFFFkhông phải là điểm mã hợp lệ bằng Unicode; chúng không nên xuất hiện dưới dạng được mã hóa theo UTF-8.
Khi bạn thấy ký tự “�” trên màn hình , rất có thể đó là do sự không khớp mã hóa hoặc tệp được lưu ở bảng mã khác. Giải pháp là buộc mã hóa UTF-8 từ đầu đến cuối (tệp, máy chủ, cơ sở dữ liệu, tiêu đề HTTP).
UTF-8 trên web và trong email
Một trang HTML chỉ cần khai báo một mã hóa duy nhất . Mã hóa được khuyến nghị, vì tính tương thích và phạm vi ứng dụng, là UTF-8. Hãy thêm thẻ meta sau vào phần tiêu đề càng sớm càng tốt:
<meta charset="UTF-8">
Hãy đặt nó ở đầu thẻ `<head>` để trình duyệt đọc nó trước khi xử lý tài liệu. Điều này giúp tránh sự không nhất quán và các ký tự "bị lỗi". Việc áp dụng UTF-8 trên web đang rất phổ biến ; nó được sử dụng bởi phần lớn các trang web hiện nay.
Trong email, UTF-8 được hỗ trợ rộng rãi và được khuyến nghị bởi các tổ chức như Internet Mail Consortium. Việc cấu hình các ứng dụng email để sử dụng UTF-8 giúp giảm thiểu các vấn đề khi trao đổi tin nhắn với những người nói các ngôn ngữ khác.
UTF-8, UTF-16 và UTF-32: Sự khác biệt là gì?
UTF-8 : Mã hóa độ dài thay đổi theo đơn vị 8 bit; lý tưởng cho web , rất hiệu quả với ASCII và các ngôn ngữ phương Tây. Khả năng tương thích và phát hiện lỗi tuyệt vời.
UTF-16 : độ dài thay đổi theo đơn vị 16 bit; sử dụng các cặp ký tự thay thế cho U+10000 trở lên. Nó thường có lợi khi các ký tự không phải ASCII chiếm ưu thế và được sử dụng trong nhiều API và nền tảng (ví dụ: Windows chạy nguyên bản ở định dạng UTF-16 ).
UTF-32 : độ dài cố định 32 bit mỗi ký tự; rất dễ lập chỉ mục , nhưng tốn nhiều không gian lưu trữ. Nó được dành cho các trường hợp mà kích thước không phải là yếu tố quan trọng hàng đầu so với sự đơn giản trong xử lý.
Các biến thể không tương thích: CESU-8 và “UTF-8 đã sửa đổi”
CESU-8 mã hóa trực tiếp các đơn vị UTF-16 (bao gồm cả các cặp ký tự thay thế) thay vì mã hóa các điểm mã, do đó khác với UTF-8 chuẩn đối với các ký tự trên U+FFFF. Một số nền tảng trước đây đã sử dụng nó: Oracle 8 cung cấp nó với bí danh UTF-8, và bắt đầu từ Oracle 9, nó đã thêm UTF-8 chuẩn với một bí danh khác. Java và Tcl đã sử dụng CESU-8 trong một số ngữ cảnh nhất định.
UTF-8 được sửa đổi (ví dụ, trong môi trường Java) biểu diễn ký tự NUL (U+0000) là 0xC0 0x80 thay vì 0x00. Nó tránh được byte null trong chuỗi C nhưng không tuân thủ tiêu chuẩn UTF-8. Nhiều triển khai của phiên bản "được sửa đổi" này cũng tuân thủ CESU-8.
UTF-8 trên Windows và API: Trang mã và chuyển đổi
Windows hoạt động nội bộ ở UTF-16 (WCHAR), nhưng kể từ Windows 10 phiên bản 1903, bạn có thể buộc UTF-8 làm trang mã quy trình thông qua bản kê khai ứng dụng (thuộc tính activeCodePage). Điều này giúp mã cũ sử dụng API “-A” hoạt động dễ dàng hơn trên UTF-8.
API -A so với -W: các -A phụ thuộc vào trang mã ANSI được cấu hình (có thể là CP_UTF8), trong khi -W họ sử dụng UTF-16. Để tương tác, MultiByteToWideChar y WideCharToMultiByte cho phép bạn chuyển đổi giữa UTF-8 và UTF-16; Hoa Kỳ CP_UTF8 và, nếu có thể áp dụng, MB_ERR_INVALID_CHARS để phát hiện lỗi nhập liệu.
UTF-8 tương thích với các trình duyệt hiện đại (Chrome, Firefox, Safari, Edge, Opera và các phiên bản Internet Explorer gần đây) và hầu hết các hệ điều hành (Windows, Linux, macOS, Android, iOS). Trừ khi bạn sử dụng phần mềm rất cũ, bạn sẽ không gặp vấn đề gì.
Cách chuyển đổi tệp sang UTF-8
Trong Windows (Notepad) : mở tệp, vào "Tệp > Lưu thành...", và trong "Mã hóa" chọn UTF-8 . Lưu với tên mới nếu bạn muốn giữ lại tệp gốc.
Trên macOS (TextEdit) : Trong “TextEdit > Tùy chọn > Mở & Lưu”, chọn Unicode (UTF-8) khi lưu. Sau đó xuất tệp với tùy chọn đó được bật.
Trên Linux: với thiết bị đầu cuối bạn có thể sử dụng iconv. Ví dụ: iconv -f <codificación_origen> -t UTF-8 <entrada> -o <salida>. Kiểm tra sau rằng ứng dụng sử dụng nó cũng mong đợi UTF-8.
Làm thế nào để biết một tệp có phải là UTF-8 hay không? Nhiều trình soạn thảo hiện đại hiển thị điều này trên thanh trạng thái. Nếu bạn thấy các ký tự lạ như “�”, dấu phụ bị lỗi hoặc “ñ/ç” hiển thị không chính xác, hãy kiểm tra mã hóa tệp và cài đặt trình soạn thảo/máy chủ/cơ sở dữ liệu.
Thực hành tốt để tránh bất ngờ
Khai báo UTF-8 càng sớm càng tốt trong HTML và tiêu đề HTTP. Đồng bộ hóa mã hóa trong toàn bộ hệ thống (tệp nguồn, mẫu, cơ sở dữ liệu và kết nối). Tránh trộn lẫn các mã hóa trên cùng một trang hoặc luồng xử lý, và sử dụng các công cụ xác thực/chuẩn hóa dữ liệu đầu vào.
Dành cho tích hợp và API, luôn luôn chỉ định mã hóa trong tiêu đề (Content-Type: application/json; charset=UTF-8, ví dụ). Kiểm tra với dữ liệu đa ngôn ngữ (giọng, CJK, biểu tượng cảm xúc) để phát hiện điểm yếu trước khi sản xuất.
UTF-8 được ưa chuộng vì nó cân bằng giữa khả năng tương thích, hiệu quả và phạm vi ứng dụng . Đây là cách thiết thực nhất để đảm bảo văn bản được truyền tải nguyên vẹn giữa các nền văn hóa, hệ thống và ứng dụng khác nhau, bất kể nó có chứa dấu phụ, ký hiệu kỹ thuật hay hệ chữ viết không phải Latinh hay không.