Unicode là charset, UTF8, UTF16 là phương thức Encode/Decode
Unicode
4
UTF8
2
Charset
2
White

Phùng Văn Tú viết ngày 02/12/2017

Chúng ta thường nghe nhiều đến Unicode, UTF-8, UTF16, hay Shift-JS.

Trong bài này chỉ xin làm rõ những khái niệm này để khi gặp phải vấn đề về Charset hay Encoding mà có phương án phù hợp.

  1. Bảng mã kí tự là gì?
  2. Encoding là gì?
  3. Unicode, Shift-JIS, UTF8, UTF16 nói lên điều gì?

1. Bảng mã kí tự là gì?

Bảng mã kí tự (char code table) là một bảng dùng để đánh chỉ số cho một tâp kí tự (char) ,sao cho mỗi kí tự được ánh xạ từ số duy nhất (code).
Giá trị của code luôn được đánh số liên tiếp tăng.
Điều này tạo sẽ tạo thứ tự cho từng kí tự trong tập kí tự ở trên.

Ta đã biết đến bảng mã ASCII:

alt text

Ở bảng trên, ta thấy cột Char, mô tả kí tự;
Các cột Dec(hay Hex) chứa giá trị ánh xạ đến kí tự tương ứng ở cột Char.

Rất dễ để hiểu khái niệm bảng mã, những cái gây khó khăn là ở phần 2

2. Encoding là gì?

Ta đã có khái niệm về bảng mã kí tự. Đến đây thôi, về cơ bản, nó chẳng khác nào cái menu bảng giá ở quán.
Giờ ta muốn sử dụng các kí tự của cái bảng đó trong máy tính tính, ta cần một phương thức để mapping các kí tự đó vào máy tính.

Miêu tả thế nào đây?
Có một phương pháp rất hay được sử dụng trong trường hợp này : Đó là mọi kí tự được lưu trữ trên bộ nhớ với cùng độ dài byte.

Nếu giá trị từ 0 ~ 100 : ta cần 1 byte ( vì giá trị có thể sẽ là khoảng: 0 ~ 255)
Nếu giá trị từ 0 ~ 60000 : ta cần 2 byte (vì giá trị có thể sẽ là khoảng: 0 ~ 65535)
Nếu giá trị từ 0 ~ 1000 : ta vẫn cần 2 byte (vì giá trị có thể sẽ là khoảng: 0 ~ 1000)d

Với phương pháp này, giá trị được lưu xuống chính là giá trị trong bảng mã kí tự ở trên, nên
các gía trị được lưu xuống đuơng nhiên giống với gía trị ghi trong bảng.

Ví dụ: Như bảng ASCII chẳng hạn, ta cần 1 byte : A -> 65 (0x41); B -> 66 (0x42)
Giả sử encoding một tập con của Unicode (từ 0x0000 -> 0xFFFF) theo cách này, ta sẽ cần 2 byte.
À -> 0x00C0 -> sẽ vẫn đuợc lưu là 0x00C0.
A -> 0x00C1 -> sẽ vẫn được lưu xuống là 0x00C1.
Nếu cứ làm với cách này mọi bảng mã đều đuợc Encode ngon lành.

Nhưng có 1 vấn đề ở đây, giả sử mọi người đều sử dụng Unicode (giá trị lớn nhất hiện tại là 0x1F8FF), tức là cần khoảng 3 byte để encode tất cả.
Nếu vậy, những tài liệu mà chỉ sử dụng ASCII sẽ có kích thước gấp 3 bình thường.
Cái này hoàn toàn không ổn. Vậy làm sao????
Một nguyên nhân nữa liên quan đến lịch sử. Đó là trước khi máy tính được phổ biến mọi nơi, thì nó hầu như chỉ được sử ở Mỹ.
Và bảng mã được sử dụng phổ biến ở hầu hết các máy tính là ASCII, và phương thức mã hóa với độ dài cố định 1 byte.
Giờ xuất hiện thêm rất nhiều kí tự, người ta sẽ làm gi?
Việc sử dụng bảng mã mới là đương nhiên, nhưng phương thức mã hóa sẽ như thế nào? Liệu họ có bỏ phương thức độ dài cố định 1 byte để thay thế bằng cố định nhiều byte???

3. Unicode, Shift-JS, UTF8, UTF16

Unicode là bảng mã chứa gần như toàn bộ các kí tự của hầu hết các ngôn ngữ trên toàn cầu.
Shift-JIS là bảng mã được sử dụng ở gần như toàn bộ các máy tính tại Nhật, được JIS đưa ra.
UTF8 là cái gì?
Là phương thức Encoding rất phổ biến để miêu tả bảng mã Unicode trên bộ nhớ.
Khi người ta thảo luận để đưa ra phương thức Encoding bảng mã Unicode này trên máy tính.
Tất nhiên họ toàn là người Mỹ, họ muốn cả thế giới có thể dùng Unicode, nhưng không muốn bỏ phương thức Encoding cũ của họ cho ASCII. Họ đưa ra cách sau:

Với các kí tự từ 0(0x00) ~ 127(0x7F) (tức là của ASCII - có 128 kí tự) : vẫn là 1 byte. : 0x*0vvvvvvv
Với các kí tự từ **0x80 ~ 0x7FF
* (có 1920 kí tự) sẽ dùng 2 byte : 0x*110vvvvv 0x10vvvvvv
Với các kí tự từ **0x800 ~ 0xFFFF
* (có 63488 kí tự) sẽ dùng 3 byte : 0x*1110vvvv 0x10vvvvvv 0x10*vvvvvv
...

alt text

Một vài ví dụ nhận đuợc từ cách Encoding trên
ASCII vẫn là ASCII, vẫn là 1 byte
Kí tự A -> 65 -> 0x41; B -> 66 -> 0x42
Kí tự ngoài ASCII sẽ như thế nào:
Á -> 0x00C0, mã binary 1100 0000, gía trị của mã này nằm ở khoảng 0x80 -> 0x7FF nên giá trị ghi xuống phải ở dạng
0x*110vvvvv 0x10vvvvvv
Sẽ encode như sau:
Ta tách 6 bit cuối của kí tự đặt vào 6 bit cuối của byte thấp, hay byte thấp sẽ có gía trị là : 0x
10000000
Còn 2 bit 11 của kí tự, ta đặt vào 2 bit cuối của byte cao, hay byte cao sẽ có giá trị là : 0x
110vvv11, các bit không đuợc đặt cho bằng 0 hết, nên byte cao sẽ có giá trị là: 0x11000011
Cuối cùng ta được giá trị Encode của Á trong bằng UTF-8 là *
0xC380**.
(Đúng theo link giáo khoa http://unicode-table.com/en/00C0/)

Cứ như vậy để mapping đến hết bảng unicode.
Ta thấy rằng, với cách encode này, giá trị trong bảng và giá trị đuợc lưu trữ không phải luôn luôn giống nhau nữa (trừ ASCII).
Ta sẽ thấy số các bit được đánh dấu đậm ở trên có giá trị cố định sẽ dùng để nhận biết.
Dựa vào các đuợc bit cố định ở đầu mỗi byte này mà chương trình đọc (editor,...) sẽ biết được đó là kí tự 1 byte (ASCII) hay kí tự nhiều byte.

Với các encode trên, các tài liệu viết bằng ASCII đương nhiên có dung lượng tối ưu.
Các kí tự châu Á hầu hết sẽ đuợc biểu diễn ở dạng 2 byte.
Điều này dẫn tới những khẳng định rằng "UTF8 là 2 byte, hay Unicode là 2 byte.".
Tiếng Việt có dấu của chúng ta 2 byte hình như là đúng, còn tất cả thì không phải. (Theo comment bạn @LeHuy11 bên dưới)

Dù có rất nhiều ưu điểm như trên. nó vẫn nhược điểm. Đó là các kí tự của một số nước mà nằm ngoài khoảng 0x80 ->0x7FF sẽ phải biểu diễn bằng 3 byte.
Dẫn đến cái đĩa cài Window cho Thái có dung lượng gấp 3 cái đĩa cài cho US???(Cái này đoán mò)
Và microsoft không dùng UTF-8 như là Encoding mặc định của họ. Dường như họ dùng UTF16. ( mong mọi người confirm giúp)

UTF16
Gần giống với cách Encode của UTF-8 nhưng nó dùng luôn 2 byte để encode cho cả ASCII.

Ví dụ A -> 65 -> 0x41 -> sẽ đuợc Encode thành 0x0041; B -> 66 -> 0x42 -> sẽ được Encode thành 0x0042.

Á -> 0x00C0 -> sẽ đuợc Encode thành 0x00C0.
À -> 0x00C1 -> sẽ đuợc Encode thành 0x00C1.
(Đúng theo link giáo khoa http://unicode-table.com/en/00C0/)

Với cách trên các kí tự ASCII sẽ có số byte gấp đôi.
Tuy nhiên dải kí tự từ 0x0000 -> 0xFFFF sẽ chỉ dùng 2 byte mà thôi.
Với khoảng này, nó phủ gần như như toàn bộ kí tự của thế giới rồi.
Đĩa cài Window ở đâu cũng như ở đâu, kích thước giống nhau. :))

@Thanks.

Sẽ bổ sung thêm BOM, UCS-2 ở một bài khác.
Link tham khảo
http://www.joelonsoftware.com/articles/Unicode.html
http://unicode-table.com

Bình luận


White
{{ comment.user.name }}
Bỏ hay Hay
{{comment.like_count}}
Male avatar
{{ comment_error }}
Hủy
   

Hiển thị thử

Chỉnh sửa

White

Phùng Văn Tú

13 bài viết.
83 người follow
Kipalog
{{userFollowed ? 'Following' : 'Follow'}}
Cùng một tác giả
White
26 6
4 thành phần của Embedded Linux Ta biết rằng Linux chạy ở khắp nơi từ siêu máy tính, máy chủ, máy để bàn (máy xách tay), điện thoại (android)...ch...
Phùng Văn Tú viết hơn 1 năm trước
26 6
White
19 5
Gần đây tôi có dịp đụng vào CMake, nên có tìm hiểu một chút về nó. Hy vọng có ích cho anh em. Nó cung cấp tính năng sinh ra Makefile một cách hiệu...
Phùng Văn Tú viết 3 năm trước
19 5
White
17 9
Thấy có bạn nói về Linux nên làm post hóng cao thủ.:)) Bài này sẽ làm một ví dụ để chỉ ra sự liên quan giữa các thành phần của một hệ thống Linux ...
Phùng Văn Tú viết hơn 1 năm trước
17 9
Bài viết liên quan
White
12 0
Chào mừng các bạn đã quay lại với series Phản Phác Quy Chân. Lần này series sẽ tập trung giải thích mổ xẻ tất tần tật về Unicode, encode và charset...
Huy Hoàng Phạm viết hơn 2 năm trước
12 0
{{like_count}}

kipalog

{{ comment_count }}

bình luận

{{liked ? "Đã kipalog" : "Kipalog"}}


White
{{userFollowed ? 'Following' : 'Follow'}}
13 bài viết.
83 người follow

 Đầu mục bài viết

Vẫn còn nữa! x

Kipalog vẫn còn rất nhiều bài viết hay và chủ đề thú vị chờ bạn khám phá!