Sự khác biệt giữa UTF-8 và Unicode là gì?


503

Tôi đã nghe những ý kiến ​​trái ngược từ mọi người - theo trang Wikipedia UTF-8 .

Họ là những điều tương tự, phải không? Ai đó có thể làm rõ?


1
Những gì WIKI này viết về unicode và UTFs là ổn theo quan điểm của tôi. Một số ý kiến ​​về nó là nghiêm trọng hơn: "Có thể trong UTF-8 (hoặc bất kỳ mã hóa đa byte nào khác) để tách hoặc cắt một chuỗi ở giữa một ký tự, điều này có thể dẫn đến một chuỗi không hợp lệ." Vì vậy, một chuỗi được mã hóa UTF-8 không còn là một chuỗi mà là một mảng byte hoặc luồng byte. Các ký tự tạo nên chuỗi được mã hóa. Tất nhiên nó cũng có thể được giải mã. Bây giờ tất nhiên bạn có thể cắt một chuỗi utf-8 sau byte bắt đầu hoặc sau một byte sau nhưng tại sao ai đó nên làm điều này?
sáng

Bài viết này về các kiểu dữ liệu chuỗi có tính giáo dục: mortoray.com/2013/11/27/the-opes-type-is-broken - đôi khi khi làm việc với các chuỗi và các thành phần mức byte của chúng, bạn có thể vô tình cắt một nửa ký tự .
Everett

Câu trả lời:


495

Để mở rộng câu trả lời mà người khác đã đưa ra:

Chúng tôi đã có rất nhiều ngôn ngữ với nhiều ký tự mà máy tính sẽ hiển thị lý tưởng. Unicode gán cho mỗi ký tự một số duy nhất hoặc điểm mã.

Máy tính xử lý các số như byte ... bỏ qua một chút lịch sử ở đây và bỏ qua các vấn đề giải quyết bộ nhớ, máy tính 8 bit sẽ coi một byte 8 bit là đơn vị số lớn nhất dễ dàng biểu thị trên phần cứng, máy tính 16 bit sẽ mở rộng đến hai byte, v.v.

Các mã hóa ký tự cũ như ASCII có từ thời đại 8 bit (trước) và cố gắng nhồi nhét ngôn ngữ thống trị trong điện toán vào thời điểm đó, tức là tiếng Anh, thành các số từ 0 đến 127 (7 bit). Với 26 chữ cái trong bảng chữ cái, cả ở dạng viết hoa và không viết hoa, số và dấu chấm câu, hoạt động khá tốt. ASCII đã được mở rộng thêm 8 bit cho các ngôn ngữ khác, không phải tiếng Anh, nhưng 128 số / điểm mã bổ sung có sẵn của bản mở rộng này sẽ được ánh xạ tới các ký tự khác nhau tùy thuộc vào ngôn ngữ được hiển thị. Các tiêu chuẩn ISO-8859 là các hình thức phổ biến nhất của ánh xạ này; ISO-8859-1 và ISO-8859-15 (còn được gọi là ISO-Latin-1, latin1, và vâng, có hai phiên bản khác nhau của tiêu chuẩn ISO 8859).

Nhưng điều đó là không đủ khi bạn muốn thể hiện các ký tự từ nhiều ngôn ngữ, vì vậy việc nhồi nhét tất cả các ký tự có sẵn vào một byte sẽ không hoạt động.

Về cơ bản có hai loại mã hóa khác nhau: một loại mở rộng phạm vi giá trị bằng cách thêm nhiều bit. Ví dụ về các bảng mã này sẽ là UCS2 (2 byte = 16 bit) và UCS4 (4 byte = 32 bit). Họ bị vấn đề tương tự như các tiêu chuẩn ASCII và ISO-8859, vì phạm vi giá trị của chúng vẫn còn hạn chế, ngay cả khi giới hạn cao hơn rất nhiều.

Loại mã hóa khác sử dụng số byte thay đổi trên mỗi ký tự và mã hóa được biết đến nhiều nhất cho điều này là mã hóa UTF. Tất cả các mã hóa UTF hoạt động theo cách gần giống nhau: bạn chọn kích thước đơn vị, đối với UTF-8 là 8 bit, đối với UTF-16 là 16 bit và đối với UTF-32 là 32 bit. Sau đó, tiêu chuẩn định nghĩa một vài trong số các bit này là cờ: nếu chúng được đặt, thì đơn vị tiếp theo trong chuỗi đơn vị sẽ được coi là một phần của cùng một ký tự. Nếu chúng không được đặt, đơn vị này thể hiện đầy đủ một ký tự. Do đó, các ký tự (tiếng Anh) phổ biến nhất chỉ chiếm một byte trong UTF-8 (hai trong UTF-16, 4 trong UTF-32), nhưng các ký tự ngôn ngữ khác có thể chiếm sáu byte trở lên.

Mã hóa nhiều byte (tôi nên nói là đa đơn vị sau khi giải thích ở trên) có ưu điểm là chúng tương đối hiệu quả về mặt không gian, nhưng nhược điểm của các hoạt động như tìm chuỗi, so sánh, v.v ... đều phải giải mã các ký tự thành mã unicode điểm trước khi các hoạt động như vậy có thể được thực hiện (mặc dù có một số phím tắt).

Cả tiêu chuẩn UCS và tiêu chuẩn UTF đều mã hóa các điểm mã như được định nghĩa trong Unicode. Về lý thuyết, các mã hóa đó có thể được sử dụng để mã hóa bất kỳ số nào (trong phạm vi hỗ trợ mã hóa) - nhưng tất nhiên các mã hóa này được thực hiện để mã hóa các điểm mã Unicode. Và đó là mối quan hệ của bạn giữa họ.

Windows xử lý các chuỗi được gọi là "Unicode" dưới dạng chuỗi UTF-16, trong khi hầu hết các UNIX mặc định là UTF-8 ngày nay. Các giao thức truyền thông như HTTP có xu hướng hoạt động tốt nhất với UTF-8, vì kích thước đơn vị trong UTF-8 giống như trong ASCII và hầu hết các giao thức như vậy được thiết kế trong thời đại ASCII. Mặt khác, UTF-16 cho hiệu suất xử lý / không gian trung bình tốt nhất khi đại diện cho tất cả các ngôn ngữ sống.

Tiêu chuẩn Unicode xác định ít điểm mã hơn có thể được biểu diễn trong 32 bit. Do đó, cho tất cả các mục đích thực tế, UTF-32 và UCS4 đã trở thành cùng một mã hóa, vì bạn không cần phải xử lý các ký tự nhiều đơn vị trong UTF-32.

Hy vọng rằng điền vào một số chi tiết.


9
Về mặt khái niệm, UCS-2 và UCS-4 là các bộ ký tự , không phải mã hóa ký tự (do đó là tên).
Ốc cơ khí

74
@Tuukka Lỗi trong bài đăng này là quân đoàn. Có nhiều hơn 2 phiên bản ISO 8859. ASCII không hoạt động đối với tiếng Anh, thiếu những thứ như dấu ngoặc kép, ký hiệu cent, dấu trọng âm, và nhiều hơn nữa Unicode Unicode không chỉ là tiếng Anh; Tiếng Anh cũng cần nó !! Không có mật mã nào chiếm hơn 4 byte trong mã hóa BẤT K ;; doanh nghiệp 6 byte này không rõ ràng. Bạn không thể mã hóa UTF bất kỳ giá trị vô hướng Unicode nào như điều này nói: thay thế & 66 ký tự không khác đều bị cấm. UCS-4 và UTF-32 không giống nhau. Không có UTF-32 nhiều đơn vị. UTF-16 không hiệu quả như họ giả vờ - & c & c & c!
tchrist

1
ASCII cũng không chứa ký hiệu bảng Anh £ và tất nhiên không chứa ký hiệu euro € (trẻ hơn đáng kể so với ASCII).
TRiG

1
Trông @tchrist rằng 6 byte không thể xảy ra sau khi tất cả. Xem điều này: joelonsoftware.com/articles/Unicode.html biểu thị rằng có một không gian ký tự từ 0x04000000đến 0x7FFFFFFFhoặc trong nhị phân 1111110v 10vvvvvv 10vvvvvv 10vvvvvv 10vvvvvv 10vvvvvv - và đó thực sự là 6 byte. Tuy nhiên, 6 byte là tối đa , và không phải như bài viết tuyên bố một cách khó hiểu "sáu byte trở lên ".
cú pháp

12
@syntaxerror: "Chỉ có các điểm mã 128 trở lên được lưu trữ bằng cách sử dụng 2, 3, trên thực tế, tối đa 6 byte." là chính xác khi được viết, nhưng sau đó cùng năm đó (mười hai năm trước) nó đã bị vô hiệu. vi.wikipedia.org/wiki/UTF-8 nói "Thông số ban đầu bao gồm số lượng lên tới 31 bit (giới hạn ban đầu của Bộ ký tự phổ quát). Vào tháng 11 năm 2003, UTF-8 đã bị RFC 3629 hạn chế kết thúc tại U + 10FFFF, để phù hợp với các ràng buộc của mã hóa ký tự UTF-16. Điều này đã loại bỏ tất cả các chuỗi 5 và 6 byte, và khoảng một nửa các chuỗi 4 byte. "
Vịt Mooing 24/03/2015

237

Hãy để tôi sử dụng một ví dụ để minh họa chủ đề này:

A chinese character:      汉
it's unicode value:       U+6C49
convert 6C49 to binary:   01101100 01001001

Không có gì kỳ diệu cho đến nay, nó rất đơn giản. Bây giờ, giả sử chúng ta quyết định lưu trữ ký tự này trên ổ cứng. Để làm điều đó, chúng ta cần lưu trữ ký tự ở định dạng nhị phân. Chúng tôi chỉ đơn giản có thể lưu trữ nó là '01101100 01001001'. Làm xong!

Nhưng hãy đợi một phút, là '01101100 01001001' một ký tự hay hai ký tự? Bạn biết đây là một nhân vật bởi vì tôi đã nói với bạn, nhưng khi một máy tính đọc nó, nó không có ý kiến ​​gì. Vì vậy, chúng ta cần một số loại "mã hóa" để báo cho máy tính coi nó là một.

Đây là nơi quy tắc của 'UTF-8' xuất hiện: http://www.fileformat.info/info/unicode/utf8.htm

Binary format of bytes in sequence

1st Byte    2nd Byte    3rd Byte    4th Byte    Number of Free Bits   Maximum Expressible Unicode Value
0xxxxxxx                                                7             007F hex (127)
110xxxxx    10xxxxxx                                (5+6)=11          07FF hex (2047)
1110xxxx    10xxxxxx    10xxxxxx                  (4+6+6)=16          FFFF hex (65535)
11110xxx    10xxxxxx    10xxxxxx    10xxxxxx    (3+6+6+6)=21          10FFFF hex (1,114,111)

Theo bảng trên, nếu chúng ta muốn lưu trữ ký tự này bằng định dạng 'UTF-8', chúng ta cần thêm tiền tố vào ký tự của mình bằng một số 'tiêu đề'. Ký tự tiếng Trung của chúng tôi dài 16 bit (tự đếm giá trị nhị phân), vì vậy chúng tôi sẽ sử dụng định dạng trên hàng 3 vì nó cung cấp đủ không gian:

Header  Place holder    Fill in our Binary   Result         
1110    xxxx            0110                 11100110
10      xxxxxx          110001               10110001
10      xxxxxx          001001               10001001

Viết ra kết quả trong một dòng:

11100110 10110001 10001001

Đây là giá trị UTF-8 (nhị phân) của ký tự Trung Quốc! (tự xác nhận: http://www.fileformat.info/info/unicode/char/6c49/index.htm )

Tóm lược

A chinese character:      汉
it's unicode value:       U+6C49
convert 6C49 to binary:   01101100 01001001
embed 6C49 as UTF-8:      11100110 10110001 10001001

PS Nếu bạn muốn tìm hiểu chủ đề này trong python, bấm vào đây


6
"Nhưng đợi một chút, là '01101100 01001001' một ký tự hoặc hai ký tự? Bạn biết đây là một ký tự vì tôi đã nói với bạn, nhưng khi một máy tính đọc nó, nó không có ý tưởng nào. Vì vậy, chúng tôi cần một loại" mã hóa "để nói với máy tính coi nó là một. " Vâng, nhưng máy tính vẫn không biết nên mã hóa nó bằng utf-8?
Koray Tugay

15
@KorayTugay Máy tính không biết nên sử dụng mã hóa nào. Bạn phải nói với nó khi bạn lưu một ký tự vào một tệp và cả khi bạn đọc một ký tự từ một tệp.
Cheng

3
@Connor Máy tính không biết sử dụng định dạng nào. Khi bạn lưu tài liệu, trình soạn thảo văn bản phải đặt mã hóa rõ ràng thành utf-8 hoặc bất kỳ định dạng nào mà người dùng muốn sử dụng. Ngoài ra, khi một chương trình soạn thảo văn bản đọc một tệp, nó cần chọn sơ đồ mã hóa văn bản để giải mã chính xác. Tương tự như vậy khi bạn đang gõ và nhập một chữ cái, trình soạn thảo văn bản cần biết bạn sử dụng lược đồ nào để nó sẽ lưu chính xác.
Cheng

2
Vậy những tiêu đề đó được giải thích như thế nào? Nếu tôi nhìn vào bảng đầu tiên thì tôi nghĩ: nếu byte bắt đầu bằng bit 0thì ký tự được biểu thị bằng 1 cắn (hiện tại), nếu byte bắt đầu bằng 110thì ký tự được biểu thị bằng 2 byte (hiện tại và tiếp theo ( các bit còn lại sau 10)), nếu byte bắt đầu bằng 1110thì ký tự được biểu thị bằng 3 byte, hiện tại và 2 byte tiếp theo (các bit còn lại sau 10).
JBoy

2
Đọc 10 bài viết về UTF-8; sau khi đọc xong tôi đã hiểu trong vòng 10 giây :)
jrhee17

201

"Unicode" không may được sử dụng theo nhiều cách khác nhau, tùy thuộc vào ngữ cảnh. Cách sử dụng đúng nhất của nó (IMO) là một bộ ký tự được mã hóa - tức là một bộ ký tự và ánh xạ giữa các ký tự và các điểm mã nguyên biểu thị chúng.

UTF-8 là một mã hóa ký tự - một cách chuyển đổi từ chuỗi byte sang chuỗi ký tự và ngược lại. Nó bao gồm toàn bộ bộ ký tự Unicode. ASCII được mã hóa dưới dạng một byte cho mỗi ký tự và các ký tự khác lấy nhiều byte hơn tùy thuộc vào điểm mã chính xác của chúng (tối đa 4 byte cho tất cả các điểm mã được xác định hiện tại, tức là lên đến U-0010FFFF và thực sự 4 byte có thể đối phó với tối đa U-001FFFFF).

Khi "Unicode" được sử dụng làm tên của mã hóa ký tự (ví dụ như thuộc tính .NET Encoding.Unicode ), nó thường có nghĩa là UTF-16 , mã hóa hầu hết các ký tự phổ biến thành hai byte. Một số nền tảng (đặc biệt là .NET và Java) sử dụng UTF-16 làm mã hóa ký tự "gốc" của chúng. Điều này dẫn đến các vấn đề về lông nếu bạn cần lo lắng về các ký tự không thể được mã hóa trong một giá trị UTF-16 (chúng được mã hóa thành "cặp thay thế") - nhưng hầu hết các nhà phát triển không bao giờ lo lắng về điều này, IME.

Một số tài liệu tham khảo về Unicode:


16
Tôi nghĩ UTF-16 chỉ bằng "Unicode" trên nền tảng Windows. Mọi người có xu hướng sử dụng UTF-8 theo mặc định trên * nix. +1 mặc dù, câu trả lời tốt
jalf

10
@Chris: Không, ISO-8859-1 không phải là UTF-8. UTF-8 mã hóa U + 0080 thành U + 00FF dưới dạng hai byte, không phải một byte. Windows 1252 và ISO-8859-1 hầu hết giống nhau, nhưng chúng khác nhau giữa các giá trị 0x80 và 0x99 nếu tôi nhớ chính xác, trong đó ISO 8859-1 có "lỗ" nhưng CP1252 xác định các ký tự.
Jon Skeet

13
Ý tưởng gọi UTF-16 "Unicode" không thoải mái với tôi do tiềm năng của nó gây nhầm lẫn - mặc dù điều này rõ ràng chỉ được coi là một quy ước .NET. UTF-16 là một cách để thể hiện Unicode, nhưng nó không phải là "Mã hóa Unicode".
thomasrutter

6
@unwesen: UTF-8 không cần cặp thay thế. Nó chỉ đại diện cho các ký tự không phải BMP sử dụng các chuỗi byte dài hơn.
Jon Skeet

5
@RoyiNamir: Có, "Unicode" không may thường được sử dụng để có nghĩa là "UTF-16" đặc biệt trong Windows.
Jon Skeet

108

Chúng không giống nhau - UTF-8 là một cách mã hóa Unicode cụ thể.

Có rất nhiều mã hóa khác nhau mà bạn có thể chọn tùy thuộc vào ứng dụng của bạn và dữ liệu bạn định sử dụng. Phổ biến nhất là UTF-8, UTF-16 và UTF-32 s theo như tôi biết.


10
tuy nhiên, vấn đề là một số biên tập viên đề xuất lưu tệp dưới dạng "Unicode" HOẶC "UTF-8". Vì vậy, đề cập về "Unicode" trong trường hợp đó là UTF-16 tôi tin là cần thiết.
serhio

71

Unicode chỉ xác định các điểm mã , nghĩa là một số đại diện cho một ký tự. Cách bạn lưu trữ các điểm mã này trong bộ nhớ tùy thuộc vào mã hóa mà bạn đang sử dụng. UTF-8 là một cách mã hóa các ký tự Unicode, trong số nhiều cách khác.


2
tuy nhiên, vấn đề là một số biên tập viên đề xuất lưu tệp dưới dạng "Unicode" HOẶC "UTF-8". Vì vậy, đề cập về "Unicode" trong trường hợp đó là UTF-16 tôi tin là cần thiết.
serhio

Một số, trình bày một nhân vật cũng làm ASCII.
sáng

6
đọc trước và sau khi nhìn vào phần còn lại của câu trả lời trên trang này
Dodgie

33

Unicode là một tiêu chuẩn xác định, cùng với ISO / IEC 10646, Bộ ký tự phổ quát (UCS) , là siêu ký tự của tất cả các ký tự hiện có được yêu cầu để thể hiện thực tế tất cả các ngôn ngữ đã biết.

Unicode gán Tên và Số ( Mã ký tự hoặc Điểm mã ) cho mỗi ký tự trong tiết mục của nó.

Mã hóa UTF-8 , là một cách để thể hiện các ký tự này bằng kỹ thuật số trong bộ nhớ máy tính. UTF-8 ánh xạ mỗi điểm mã thành một chuỗi các octet (byte 8 bit)

Ví dụ:

Ký tự UCS = Ký tự chữ Hán

Điểm mã UCS = U + 24B62

Mã hóa UTF-8 = F0 A4 AD A2 (hex) = 11110000 10100100 10101101 10100010 (bin)


Không, UTF-8 chỉ ánh xạ các điểm mã thành một chuỗi lớn hơn 127. Mọi thứ từ 0 đến 127 không phải là một chuỗi mà là một byte đơn. Btw, ASCII cũng gán Tên của một ký tự cho một số, vì vậy đây giống như những gì Unicode làm. Nhưng Unicode không dừng lại ở điểm mã 127 mà tăng lên 0x10ffff.
sáng

2
@brightly tôi khác. Các ký tự Ascii thực sự được ánh xạ tới một chuỗi byte đơn. Bit đầu tiên, là 0 trong trường hợp mã cho các ký tự ascii, cho biết có bao nhiêu byte theo sau - zero. http://www.wikiwand.com/en/UTF-8#/DescriptionCó một cái nhìn vào hàng đầu tiên.
nightlytrails

Đối với tôi, một chuỗi bao gồm nhiều hơn một byte. Một ký tự ASCII trong UTF-8 là một byte đơn, với bit đáng kể nhất được đặt thành 0. Các điểm mã cao hơn 127 sau đó cần các chuỗi, luôn có một startbyte và một, hai hoặc ba byte sau. Vậy tại sao bạn lại gọi một byte là "chuỗi"?
sáng

Chà ... Nhiều lần luật sư tiếng Anh có thể gặp khó khăn vì sự lạm dụng có chủ ý trong phần mềm. Đây là trường hợp tương tự ở đây. Bạn có thể tranh luận về nó. Nhưng điều đó sẽ không làm cho nó rõ ràng hơn.
nightlytrails

1
@brighty Hmmm, Trong toán học, một chuỗi gồm 0 phần tử. Một chuỗi gồm 1 phần tử cũng tốt ở đây.
chux - Phục hồi Monica

24

Unicode chỉ là một tiêu chuẩn xác định một bộ ký tự ( UCS ) và mã hóa ( UTF ) để mã hóa bộ ký tự này. Nhưng nói chung, Unicode được giới thiệu đến bộ ký tự và không phải là tiêu chuẩn.

Đọc Tối thiểu tuyệt đối Mỗi nhà phát triển phần mềm Tuyệt đối, Phải tích cực phải biết về Unicode và Bộ ký tự (Không có lý do!)Unicode trong 5 phút .


1
@serhio: Tôi biết. Mặc dù có ba bảng mã UTF-16 khác nhau: Hai UTF-16LEUTF-16BE rõ ràng và UTF-16 ẩn trong đó độ bền được xác định bằng BOM.
Gumbo

@Gumbo: Việc thiếu BOM không có nghĩa đó là một mã hóa khác. Chỉ có hai bảng mã.
Vịt Mooing 24/03/2015

Blog trên được viết bởi CEO của Stakcoverflow.
Shailesh Pratapwar

23

Các câu trả lời hiện có đã giải thích rất nhiều chi tiết, nhưng đây là một câu trả lời rất ngắn với lời giải thích và ví dụ trực tiếp nhất.

Unicode là tiêu chuẩn ánh xạ các ký tự thành các điểm mã.
Mỗi ký tự có một mật mã duy nhất (số nhận dạng), là một số như 9731.

UTF-8 là một sự mã hóa của codepoints.
Để lưu trữ tất cả các ký tự trên đĩa (trong một tệp), UTF-8 chia các ký tự thành tối đa 4 octet (chuỗi 8 bit) - byte. UTF-8 là một trong một số mã hóa (phương pháp biểu diễn dữ liệu). Ví dụ: trong Unicode, mã số (thập phân) 9731 đại diện cho người tuyết ( ), bao gồm 3 byte trong UTF-8:E2 98 83

Đây là một danh sách được sắp xếp với một số ví dụ ngẫu nhiên .


1
Không! UTF-8 là một cách hay để mã hóa các ký tự unicode nhưng chúng ta cũng có thể mã hóa bằng UTF-16 hoặc UTF-32. Với UTF-32, chúng tôi có mối quan hệ 1: 1 giữa DWORD và codepoint, với UTF-16, chúng tôi có mối quan hệ 1: 1 giữa WORD và codepoint chỉ cho các điểm mã của BMP, ngoại trừ các đại diện thay thế và BOM. Trong UTF-8, chúng tôi có mối quan hệ 1: 1 giữa byte và tiền mã hóa chỉ dành cho tiền mã hóa <127
sáng

5
@brighty: Phải, nhưng tại sao "Không!"? Tôi đã viết "UTF-8 là một trong nhiều bảng mã" bởi vì cũng có UTF-16 và UTF-32.
bản6

16

1. Unicode

Có rất nhiều nhân vật trên khắp thế giới, như "$, &, h, a, t,?,, 1, =, + ...".

Sau đó, có một tổ chức dành riêng cho những nhân vật này,

Họ đã tạo ra một tiêu chuẩn gọi là "Unicode".

Tiêu chuẩn như sau:

  • tạo một biểu mẫu trong đó mỗi vị trí được gọi là "điểm mã" hoặc "vị trí mã".
  • Toàn bộ các vị trí từ U + 0000 đến U + 10FFFF;
  • Cho đến bây giờ, một số vị trí chứa đầy các ký tự và các vị trí khác được lưu hoặc trống.
  • Ví dụ: vị trí "U + 0024" được điền với ký tự "$".

PS: Tất nhiên có một tổ chức khác gọi là ISO duy trì một tiêu chuẩn khác - "ISO 10646" gần giống nhau.

2. UTF-8

Như trên, U + 0024 chỉ là một vị trí, vì vậy chúng tôi không thể lưu "U + 0024" trong máy tính cho ký tự "$".

Phải có một phương pháp mã hóa.

Sau đó, đến các phương thức mã hóa, chẳng hạn như UTF-8, UTF-16, UTF-32, UCS-2 ....

Theo UTF-8, điểm mã "U + 0024" được mã hóa thành 00100100.

00100100 là giá trị chúng tôi lưu trong máy tính với giá "$".


1
Nhìn chung, UTF-8 là biến thể duy nhất mà bất cứ ai sử dụng ngày nay.
Rick James

2
ISO 10646 là một tiêu chuẩn giống hệt với bộ ký tự Unicode. Unicode định nghĩa rất nhiều thứ khác ngoài bộ ký tự, chẳng hạn như quy tắc sắp xếp, trường hợp, v.v. ISO 10646 chỉ là bộ ký tự (trong đó hiện có hơn 130.000). Unicode Consortium và ISO cùng phát triển Unicode, với ISO chỉ liên quan đến bộ ký tự và mã hóa của nó, và Unicode cũng xác định các thuộc tính và quy tắc ký tự để xử lý văn bản.
thomasrutter

12

Tôi đã kiểm tra các liên kết trong câu trả lời của Gumbo và tôi cũng muốn dán một phần của những thứ đó vào đây để tồn tại trên Stack Overflow.

"... Một số người theo quan niệm sai lầm rằng Unicode chỉ đơn giản là mã 16 bit trong đó mỗi ký tự lấy 16 bit và do đó có 65.536 ký tự có thể. Thực tế, đây không phải là chính xác. Đây là huyền thoại phổ biến nhất về Unicode , vì vậy nếu bạn nghĩ vậy, đừng cảm thấy tồi tệ.

Trên thực tế, Unicode có cách nghĩ khác về các ký tự và bạn phải hiểu cách suy nghĩ của Unicode về mọi thứ hoặc không có gì có ý nghĩa.

Cho đến bây giờ, chúng tôi đã giả sử rằng một chữ cái ánh xạ tới một số bit mà bạn có thể lưu trữ trên đĩa hoặc trong bộ nhớ:

A -> 0100 0001

Trong Unicode, một chữ cái ánh xạ tới một thứ gọi là điểm mã vẫn chỉ là một khái niệm lý thuyết. Làm thế nào điểm mã được thể hiện trong bộ nhớ hoặc trên đĩa là cả một câu chuyện khác ... "

"... Mỗi chữ cái trong mỗi bảng chữ cái được gán một số ma thuật bởi tập đoàn Unicode được viết như sau: U + 0639. Số ma thuật này được gọi là điểm mã. U + có nghĩa là" Unicode "và các số là thập lục phân. U + 0639 là chữ cái Ả Rập Ain. Chữ cái tiếng Anh A sẽ là U + 0041 .... "

"... OK, vì vậy giả sử chúng ta có một chuỗi:

xin chào

trong Unicode, tương ứng với năm điểm mã sau:

U + 0048 U + 0065 U + 006C U + 006C U + 006F.

Chỉ là một loạt các điểm mã. Những con số, thực sự. Chúng tôi chưa nói gì về cách lưu trữ thứ này trong bộ nhớ hoặc thể hiện nó trong thông điệp email ... "

"... Đó là nơi mã hóa đi vào.

Ý tưởng sớm nhất về mã hóa Unicode, dẫn đến huyền thoại về hai byte, là, chúng ta hãy lưu trữ các số đó trong hai byte mỗi byte. Vì vậy, Xin chào trở thành

00 48 00 65 00 6C 00 6C 00 6F

Đúng? Không quá nhanh! Cũng không thể:

48 00 65 00 6C 00 6C 00 6F 00? ... "


Trong ASCII, một chữ cái cũng ánh xạ tới một mật mã, không chỉ ở dạng unicode.
sáng

8

UTF-8 là một sơ đồ mã hóa có thể có cho Unicode văn bản .

Unicode là một tiêu chuẩn có phạm vi rộng, xác định hơn 130.000 ký tự và phân bổ cho mỗi mã số (một điểm mã). Nó cũng xác định các quy tắc về cách sắp xếp văn bản này, bình thường hóa nó, thay đổi trường hợp của nó và hơn thế nữa. Một ký tự trong Unicode được biểu thị bằng một điểm mã từ 0 đến 0x10FFFF, mặc dù một số điểm mã được dành riêng và không thể được sử dụng cho các ký tự.

Có nhiều hơn một cách mà một chuỗi các điểm mã Unicode có thể được mã hóa thành một luồng nhị phân. Chúng được gọi là "mã hóa". Mã hóa đơn giản nhất là UTF-32 , chỉ đơn giản lưu trữ mỗi điểm mã dưới dạng số nguyên 32 bit, mỗi mã có chiều rộng 4 byte.

UTF-8 là một mã hóa khác, và đang trở thành tiêu chuẩn thực tế, do một số lợi thế so với UTF-32 và các loại khác. UTF-8 mã hóa thành một chuỗi các giá trị byte đơn. Mỗi điểm mã có thể sử dụng một số lượng khác nhau của các giá trị byte này. Các điểm mã trong phạm vi ASCII được mã hóa trần, để tương thích với ASCII. Các điểm mã nằm ngoài phạm vi này sử dụng số byte thay đổi, 2, 3 hoặc 4, tùy thuộc vào phạm vi chúng nằm trong phạm vi nào.

UTF-8 đã được thiết kế với các đặc tính này:

  • Các ký tự ASCII được mã hóa chính xác như trong ASCII, sao cho chuỗi ASCII cũng là chuỗi UTF-8 hợp lệ.

  • Sắp xếp nhị phân: Sắp xếp các chuỗi UTF-8 bằng cách sử dụng sắp xếp nhị phân ngây thơ sẽ vẫn dẫn đến tất cả các điểm mã được sắp xếp theo thứ tự số.

  • Các ký tự yêu cầu nhiều byte không chứa bất kỳ giá trị byte nào trong phạm vi ASCII, đảm bảo một phần của chúng không thể bị nhầm với các ký tự ASCII. Đây cũng là một tính năng bảo mật.

  • UTF-8 có thể được xác nhận dễ dàng và được phân biệt với các mã hóa ký tự khác bởi một trình xác nhận. Văn bản trong các bảng mã 8 bit hoặc nhiều byte khác sẽ hiếm khi xác nhận là UTF-8.

  • Truy cập ngẫu nhiên: Tại bất kỳ điểm nào trong chuỗi UTF-8, có thể cho biết byte ở vị trí đó có phải là byte đầu tiên của ký tự hay không và để tìm bắt đầu của ký tự tiếp theo hoặc hiện tại, mà không cần phải quét về phía trước hoặc ngược hơn một vài byte hoặc đọc bất cứ thứ gì khi bắt đầu luồng.


Một vài điểm nhỏ: [1] Không nên thay đổi "Các ký tự ASCII được mã hóa chính xác như trong ASCII " thành "Các ký tự ASCII được mã hóa chính xác như trong UTF-8 " ? [2] Cụm từ "Các mã trong Unicode ..." không rõ ràng (với tôi). Ý bạn là "điểm mã Unicode ..." ?
skomisa

@skomisa cho điểm 1, ý tôi là mã hóa các ký tự trong phạm vi ASCII giống hệt với ASCII và cho UTF-8.
thomasrutter

Đối với điểm 2, đó là một điểm công bằng và tôi sẽ chỉnh sửa nó để làm cho nó rõ ràng hơn
thomasrutter

2

Họ là những điều tương tự, phải không?

Không, họ không.


Tôi nghĩ rằng câu đầu tiên của trang Wikipedia mà bạn tham chiếu đưa ra một bản tóm tắt hay, ngắn gọn:

UTF-8 là mã hóa ký tự có chiều rộng thay đổi có khả năng mã hóa tất cả 1.112.064 điểm mã hợp lệ trong Unicode bằng cách sử dụng một đến bốn byte 8 bit.

Để giải thích:

  • Unicode là một tiêu chuẩn, định nghĩa một bản đồ từ các ký tự đến các số, được gọi là các điểm mã , (như trong ví dụ dưới đây). Đối với bản đồ đầy đủ, bạn có thể có một cái nhìn ở đây .

    ! -> U+0021 (21),  
    " -> U+0022 (22),  
    \# -> U+0023 (23)
    
  • UTF-8 là một trong những cách để mã hóa các điểm mã này dưới dạng máy tính có thể hiểu, còn gọi là bit . Nói cách khác, đó là một cách / thuật toán để chuyển đổi từng điểm mã đó thành một chuỗi bit hoặc chuyển đổi một chuỗi bit thành các điểm mã tương đương. Lưu ý rằng có rất nhiều bảng mã thay thế cho Unicode.


Joel đưa ra một lời giải thích thực sự tốt đẹp và một cái nhìn tổng quan về lịch sử ở đây .


2

Nếu tôi có thể tóm tắt những gì tôi thu thập được từ chủ đề này:

Unicode 'dịch các ký tự thành số thứ tự (ở dạng thập phân) .

à = 224

UTF-8 là một mã hóa 'dịch' các số này thành các biểu diễn nhị phân .

224 = 11000011 10100000

Lưu ý rằng chúng ta đang nói về biểu diễn nhị phân của 224, không phải dạng nhị phân của nó, là 0b11100000.


2

Bài viết này giải thích tất cả các chi tiết http://kunststube.net/encoding/

VIẾT ĐỂ BUFFER

nếu bạn ghi vào bộ đệm 4 byte, ký hiệu có mã hóa UTF8, tệp nhị phân của bạn sẽ trông như thế này:

00000000 11100011 10000001 10000010

nếu bạn ghi vào bộ đệm 4 byte, ký hiệu có mã hóa UTF16, tệp nhị phân của bạn sẽ trông như thế này:

00000000 00000000 00110000 01000010

Như bạn có thể thấy, tùy thuộc vào ngôn ngữ bạn sẽ sử dụng trong nội dung của mình, điều này sẽ ảnh hưởng đến bộ nhớ của bạn.

ví dụ: Đối với biểu tượng cụ thể này: mã hóa UTF16 hiệu quả hơn vì chúng tôi có 2 byte dự phòng để sử dụng cho biểu tượng tiếp theo. Nhưng điều đó không có nghĩa là bạn phải sử dụng bảng chữ cái UTF16 cho Nhật Bản.

ĐỌC TỪ BUFFER

Bây giờ nếu bạn muốn đọc các byte ở trên, bạn phải biết nó được viết mã hóa và giải mã lại chính xác.

ví dụ: Nếu bạn giải mã điều này: 00000000 11100011 10000001 10000010 thành mã hóa UTF16, bạn sẽ không

Lưu ý: Mã hóa và Unicode là hai thứ khác nhau. Unicode là bảng (bảng) lớn với mỗi ký hiệu được ánh xạ tới một điểm mã duy nhất. ví dụ: ký hiệu (chữ cái) có (điểm mã) : 30 42 (hex). Mặt khác, mã hóa là một thuật toán chuyển đổi các ký hiệu thành cách thích hợp hơn, khi lưu trữ vào phần cứng.

30 42 (hex) - > UTF8 encoding - > E3 81 82 (hex), which is above result in binary.

30 42 (hex) - > UTF16 encoding - > 30 42 (hex), which is above result in binary.

nhập mô tả hình ảnh ở đây


bài viết được liên kết rất tốt, hy vọng nó tiếp tục duy trì hoạt động
yolob 21 tháng

0

UTF-8 là một phương pháp để mã hóa các ký tự Unicode bằng cách sử dụng các chuỗi 8 bit.

Unicode là một tiêu chuẩn để đại diện cho rất nhiều ký tự từ nhiều ngôn ngữ.


4
"Chuỗi 8 bit" SẠC? Có thể muốn xác định chính xác hơn nữa
lừa dối
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.