UTF-8 có thể mã hóa bao nhiêu ký tự?


97

Nếu UTF-8 là 8 bit, không có nghĩa là chỉ có thể có tối đa 256 ký tự khác nhau?

128 điểm mã đầu tiên giống như trong ASCII. Nhưng nó nói rằng UTF-8 có thể hỗ trợ tới hàng triệu ký tự?

Cái này hoạt động ra sao?


2
nếu bạn có thể vui lòng đánh giá lại câu hỏi này vì tất cả các câu trả lời đều sai. Đọc câu trả lời của tôi: stackoverflow.com/a/45042566/124486
Evan Carroll

Trong các bảng mã UTF-8, UTF-16, UTF-32 của Unicode, số là số bit trong các đơn vị mã của nó , một hoặc nhiều trong số đó mã hóa một điểm mã Unicode.
Tom Blodget,

1
Tôi đã trả lời câu hỏi này một lúc trước trong một nỗ lực cố gắng làm thẳng nó: sẽ thật tuyệt nếu bạn cân nhắc nó với câu trả lời đã chọn, theo nghĩa đen chỉ là một câu trích dẫn wikipedia không kể toàn bộ câu chuyện (hy vọng cập nhật của tôi rõ ràng hơn rất nhiều)
Evan Carroll

Câu trả lời:


135

UTF-8 không sử dụng một byte mọi lúc, nó là 1 đến 4 byte.

128 ký tự đầu tiên (US-ASCII) cần một byte.

1.920 ký tự tiếp theo cần hai byte để mã hóa. Điều này bao gồm phần còn lại của hầu hết các bảng chữ cái Latinh, và cả các bảng chữ cái Hy Lạp, Cyrillic, Coptic, Armenia, Hebrew, Ả Rập, Syriac và Tāna, cũng như Kết hợp các dấu phụ.

Ba byte là cần thiết cho các ký tự trong phần còn lại của Mặt phẳng đa ngôn ngữ cơ bản, chứa hầu như tất cả các ký tự được sử dụng phổ biến [12] bao gồm hầu hết các ký tự [CJK] Trung Quốc, Nhật Bản và Hàn Quốc.

Bốn byte là cần thiết cho các ký tự trong các mặt phẳng khác của Unicode, bao gồm các ký tự CJK ít phổ biến hơn, các chữ viết lịch sử khác nhau, các ký hiệu toán học và biểu tượng cảm xúc (ký hiệu hình ảnh).

nguồn: Wikipedia


chào @zwippie tôi mới làm quen với cái này. Có điều gì đó tôi không hiểu.! BMP sử dụng 2 byte bạn nói là 3? Liệu tôi có sai?
chiperortiz

1
@chiperortiz, BMP thực sự là 16 bit, vì vậy nó có thể được mã hóa dưới dạng UTF-16 với độ dài không đổi cho mỗi ký tự (UTF-16 cũng hỗ trợ vượt quá 16 bit, nhưng đó là một thực tế khó và nhiều triển khai không hỗ trợ nó). Tuy nhiên, đối với UTF-8, bạn cũng cần phải mã hóa thời lượng của nó, vì vậy bạn sẽ mất một số bit. Đó là lý do tại sao bạn cần 3 byte để mã hóa BMP hoàn chỉnh. Điều này có vẻ lãng phí, nhưng hãy nhớ rằng UTF-16 luôn sử dụng 2 byte, nhưng UTF-8 sử dụng một byte cho mỗi ký tự cho hầu hết các ký tự ngôn ngữ dựa trên latin. Làm cho nó nhỏ gọn gấp đôi.
sanderd 17

Lực đẩy chính của câu hỏi của OP liên quan đến việc tại sao nó được gọi là UTF- 8 - điều này không thực sự trả lời được điều đó.
jbyrd

39

UTF-8 sử dụng 1-4 byte cho mỗi ký tự: một byte cho các ký tự ascii (128 giá trị unicode đầu tiên giống ascii). Nhưng điều đó chỉ yêu cầu 7 bit. Nếu bit ("dấu") cao nhất được đặt, điều này cho biết sự bắt đầu của một chuỗi nhiều byte; số lượng bit cao liên tiếp được thiết lập cho biết số byte, sau đó là 0 và các bit còn lại đóng góp vào giá trị. Đối với các byte khác, hai bit cao nhất sẽ là 1 và 0 và 6 bit còn lại là giá trị.

Vì vậy, một chuỗi bốn byte sẽ bắt đầu bằng 11110 ... (và ... = ba bit cho giá trị) sau đó ba byte với 6 bit mỗi giá trị, mang lại giá trị 21 bit. 2 ^ 21 vượt quá số ký tự unicode, do đó, tất cả các unicode có thể được thể hiện bằng UTF8.


@NickL. Không, ý tôi là 3 byte. Trong ví dụ đó, nếu byte đầu tiên của một chuỗi nhiều byte bắt đầu 1111, thì 1 đầu tiên chỉ ra rằng đó phần bắt đầu của một chuỗi nhiều byte, sau đó số byte 1 liên tiếp sau đó cho biết số byte bổ sung trong chuỗi (vì vậy byte sẽ bắt đầu hoặc 110, 1110 hoặc 11110).
CodeClown42

Tìm thấy bằng chứng cho lời nói của bạn trong RFC 3629. tools.ietf.org/html/rfc3629#section-3 . Tuy nhiên, tôi không hiểu tại sao tôi cần phải đặt "10" ở đầu của byte thứ hai 110xxxxx 10xxxxxx? Tại sao không chỉ 110xxxxx xxxxxxxx?
kolobok

3
Tìm thấy câu trả lời trong softwareengineering.stackexchange.com/questions/262227/… . Chỉ vì lý do an toàn (trong trường hợp một byte đơn ở giữa dòng là hỏng)
Kolobok

@kolobok À. Sau đó, bạn có thể mã hóa giá trị 21 bit thành 3 byte (3 bit cho biết độ dài, cộng với 21 bit). : D Có lẽ điều đó không có ý nghĩa lắm, ít nhất là WRT các ngôn ngữ phương Tây.
CodeClown42

Tôi đoán rằng NickL đã hỏi điều này nhưng điều gì đã xảy ra với phần còn lại của các bit trong byte đầu tiên đó nếu ... đại diện cho các byte tiếp theo thay vì các bit?
c6754,

26

Theo bảng này * UTF-8 sẽ hỗ trợ:

2 31 = 2.147.483.648 ký tự

Tuy nhiên, RFC 3629 đã hạn chế các giá trị có thể có, vì vậy bây giờ chúng tôi giới hạn ở 4 byte , điều này cho chúng tôi

2 21 = 2.097.152 ký tự

Lưu ý rằng một phần lớn các ký tự đó được "dành riêng" cho việc sử dụng tùy chỉnh, điều này thực sự khá tiện dụng cho các phông chữ biểu tượng.

* Wikipedia đã sử dụng hiển thị một bảng có 6 byte - chúng đã cập nhật bài viết.

2017-07-11: Đã sửa lỗi để đếm kép cùng một điểm mã được mã hóa bằng nhiều byte


Câu trả lời này là đếm gấp đôi số lượng mã hóa có thể. Khi bạn đã đếm tất cả 2 ^ 7, bạn không thể đếm lại chúng trong 2 ^ 11, 2 ^ 16, v.v. Số lượng mã hóa chính xác có thể có là 2 ^ 21 (mặc dù không phải tất cả hiện đang được sử dụng).
Jimmy

@Jimmy Bạn có chắc là tôi đang đếm gấp đôi không? 0xxxxxxxcung cấp 7 bit có thể sử dụng, 110xxxxx 10xxxxxxcung cấp thêm 11 bit - không có sự chồng chéo. Byte đầu tiên bắt đầu bằng 0trong trường hợp đầu tiên và 1trong trường hợp thứ hai.
mpen

@mpen vậy điểm mã nào 00000001lưu trữ và lưu trữ những gì 11000000 100000001?
Evan Carroll

1
@EvanCarroll Uhh .... lấy điểm rồi. Không nhận ra rằng có nhiều cách để mã hóa cùng một điểm mã.
mpen

1
Tôi đã đi trước một cố gắng trả lời này bản thân mình, nhìn thấy nếu bạn nghĩ rằng đây là một lời giải thích tốt hơn và trả lời cho câu hỏi: stackoverflow.com/a/45042566/124486
Evan Carroll

21

Unicode so với UTF-8

Unicode phân giải mã điểm thành các ký tự. UTF-8 là một cơ chế lưu trữ cho Unicode. Unicode có một thông số kỹ thuật. UTF-8 có một thông số kỹ thuật. Cả hai đều có những giới hạn khác nhau. UTF-8 có một giới hạn hướng lên khác.

Unicode

Unicode được chỉ định bằng "máy bay". Mỗi máy bay mang 2 mã 16 điểm. Có 17 Máy bay trong Unicode. Để biết tổng 17 * 2^16số điểm mã. Mặt phẳng đầu tiên, mặt phẳng 0 hoặc BMP , đặc biệt ở trọng lượng của những gì nó mang theo.

Thay vì giải thích tất cả các sắc thái, hãy để tôi chỉ trích dẫn bài báo trên về máy bay.

17 máy bay có thể chứa 1.114.112 điểm mã. Trong số này, 2.048 là đại diện, 66 là không phải ký tự và 137.468 được dành cho mục đích sử dụng cá nhân, còn lại 974.530 cho chuyển nhượng công khai.

UTF-8

Bây giờ chúng ta hãy quay lại bài viết được liên kết ở trên,

Sơ đồ mã hóa được UTF-8 sử dụng được thiết kế với giới hạn lớn hơn nhiều là 2 31 điểm mã (32.768 mặt phẳng) và có thể mã hóa 2 21 điểm mã (32 mặt phẳng) ngay cả khi giới hạn ở 4 byte. [3] Vì Unicode giới hạn các điểm mã trong 17 mặt phẳng có thể được mã hóa bởi UTF-16, các điểm mã trên 0x10FFFF không hợp lệ trong UTF-8 và UTF-32.

Vì vậy, bạn có thể thấy rằng bạn có thể đưa nội dung vào UTF-8 không phải là Unicode hợp lệ. Tại sao? Bởi vì UTF-8 chứa các điểm mã mà Unicode thậm chí không hỗ trợ.

UTF-8, ngay cả với giới hạn bốn byte, hỗ trợ 2 21 điểm mã, nhiều hơn17 * 2^16


18

2.164.864 “ký tự” có thể được mã hóa bởi UTF-8.

Con số này là 2 ^ 7 + 2 ^ 11 + 2 ^ 16 + 2 ^ 21 xuất phát từ cách mã hóa hoạt động:

  • Các ký tự 1 byte có 7 bit để mã hóa 0xxxxxxx(0x00-0x7F)

  • Các ký tự 2 byte có 11 bit để mã hóa 110xxxxx 10xxxxxx(0xC0-0xDF cho byte đầu tiên; 0x80-0xBF cho byte thứ hai)

  • Các ký tự 3 byte có 16 bit để mã hóa 1110xxxx 10xxxxxx 10xxxxxx(0xE0-0xEF cho byte đầu tiên; 0x80-0xBF cho byte tiếp tục)

  • Các ký tự 4 byte có 21 bit để mã hóa 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx(0xF0-0xF7 cho byte đầu tiên; 0x80-0xBF cho byte tiếp tục)

Như bạn có thể thấy, mã này lớn hơn đáng kể so với Unicode hiện tại (1.112.064 ký tự).

CẬP NHẬT

Tính toán ban đầu của tôi là sai vì nó không xem xét các quy tắc bổ sung. Xem bình luận cho câu trả lời này để biết thêm chi tiết.


2
Phép toán của bạn không tuân theo quy tắc UTF-8 rằng chỉ chuỗi đơn vị mã ngắn nhất mới được phép mã hóa một điểm mã. Vì vậy, 00000001 là hợp lệ cho U + 0001 nhưng 11110000 10000000 10000000 10000001 thì không. Tham khảo: Bảng 3-7. Trình tự UTF-8 Byte được định dạng tốt . Bên cạnh đó, câu hỏi được trả lời trực tiếp bằng bảng: bạn chỉ cần cộng các phạm vi. (Chúng riêng biệt để loại trừ các đại diện thay thế cho UTF-16).
Tom Blodget,

Tom - cảm ơn vì bình luận của bạn! Tôi đã không biết về những hạn chế đó. Tôi đã xem bảng 3-7chạy các con số và có vẻ như có 1.083.392 chuỗi hợp lệ có thể có.
Ruben Reyes

6

UTF-8 là kiểu mã hóa có độ dài thay đổi với tối thiểu 8 bit cho mỗi ký tự.
Các ký tự có điểm mã cao hơn sẽ chiếm tới 32 bit.


2
Điều này gây hiểu lầm. Điểm mã dài nhất mà bạn có thể có là 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx, vì vậy chỉ có thể sử dụng 21 bit để mã hóa ký tự thực.
Boris

5
Tôi đã nói các điểm mã có thể cần đến 32 bit để được mã hóa, tôi chưa bao giờ tuyên bố rằng (bằng cách cảm ứng) bạn có thể mã hóa 2 ^ 32 ký tự trong 32 bit UTF-8. Nhưng điều đó khá là tranh luận, vì bạn có thể mã hóa tất cả các ký tự Unicode hiện có trong UTF-8 và bạn có thể mã hóa nhiều hơn nữa nếu bạn kéo UTF-8 lên 48 bit (tồn tại nhưng không được dùng nữa), vì vậy tôi không chắc điểm gây hiểu lầm là.
dối trá


2

Kiểm tra Tiêu chuẩn Unicode và thông tin liên quan, chẳng hạn như mục Câu hỏi thường gặp, UTF-8 UTF-16, UTF-32 & BOM . Nó không phải là thuận buồm xuôi gió, nhưng đó là thông tin có thẩm quyền và phần lớn những gì bạn có thể đọc về UTF-8 ở những nơi khác đều đáng nghi ngờ.

“8” trong “UTF-8” liên quan đến độ dài của các đơn vị mã tính bằng bit. Đơn vị mã là các thực thể được sử dụng để mã hóa các ký tự, không nhất thiết như một ánh xạ một-một đơn giản. UTF-8 sử dụng một số đơn vị mã thay đổi để mã hóa một ký tự.

Tập hợp các ký tự có thể được mã hóa trong UTF-8 hoàn toàn giống với UTF-16 hoặc UTF-32, cụ thể là tất cả các ký tự Unicode. Tất cả chúng đều mã hóa toàn bộ không gian mã hóa Unicode, thậm chí bao gồm các ký tự không ký tự và các điểm mã chưa được gán.


1

Mặc dù tôi đồng ý với mpen về mã UTF-8 tối đa hiện tại (2.164.864) (được liệt kê bên dưới, tôi không thể bình luận về anh ấy), anh ấy sẽ giảm 2 cấp nếu bạn xóa 2 hạn chế chính của UTF-8: chỉ 4 byte giới hạn và mã 254 và 255 không thể được sử dụng (anh ta chỉ loại bỏ giới hạn 4 byte).

Mã bắt đầu 254 tuân theo sự sắp xếp cơ bản của các bit bắt đầu (cờ nhiều bit được đặt thành 1, số đếm là 6 1 và đầu cuối là 0, không có bit dự phòng) cung cấp cho bạn 6 byte bổ sung để làm việc với (6 nhóm 10xxxxxx, thêm 2 ^ 36 mã).

Mã bắt đầu 255 không tuân theo chính xác thiết lập cơ bản, không có đầu cuối 0 nhưng tất cả các bit đều được sử dụng, cung cấp cho bạn 7 byte bổ sung (cờ nhiều bit được đặt thành 1, số đếm 7 1 và không có đầu cuối 0 vì tất cả các bit đều được sử dụng ; 7 nhóm 10xxxxxx, thêm 2 ^ 42 mã).

Việc thêm các ký tự này vào sẽ tạo ra bộ ký tự hiển thị tối đa cuối cùng là 4,468,982,745,216. Đây là nhiều hơn tất cả các ký tự đang được sử dụng hiện tại, các ngôn ngữ cũ hoặc đã chết và bất kỳ ngôn ngữ đã mất nào được cho là. Angelic hay Celestial script ai?

Ngoài ra, có những mã byte đơn bị bỏ qua / bỏ qua trong tiêu chuẩn UTF-8 ngoài 254 và 255: 128-191 và một số mã khác. Một số được sử dụng cục bộ bởi bàn phím, ví dụ mã 128 thường là xóa lùi. Các mã bắt đầu khác (và các dải ô được kết hợp) không hợp lệ vì một hoặc nhiều lý do ( https://en.wikipedia.org/wiki/UTF-8#Invalid_byte_sequences ).


0

Unicode kết hợp chặt chẽ với UTF-8. Unicode đặc biệt hỗ trợ 2 ^ 21 điểm mã (2.097.152 ký tự), chính xác là số điểm mã được UTF-8 hỗ trợ. Cả hai hệ thống đều dành cùng một không gian 'chết' và các vùng hạn chế cho các điểm mã, v.v. ... tính đến tháng 6 năm 2018, phiên bản mới nhất, Unicode 11.0, chứa một kho gồm 137.439 ký tự

Từ tiêu chuẩn unicode. Câu hỏi thường gặp về Unicode

Chuẩn Unicode mã hóa các ký tự trong dải U + 0000..U + 10FFFF, tương đương với một không gian mã 21 bit.

Từ trang Wikipedia UTF-8. Mô tả UTF-8

Kể từ khi giới hạn không gian mã Unicode thành giá trị 21 bit vào năm 2003, UTF-8 được định nghĩa để mã hóa các điểm mã trong một đến bốn byte, ...


21 bit được làm tròn lên. Unicode hỗ trợ 1.114.112 codepoint (U + 0000 đến U + 10FFFF) như nó nói. (Đôi khi được mô tả là 17 chiếc máy bay của 65536.)
Tom Blodget

@TomBlodget, Bạn đã đúng. Điều rút ra phù hợp nhất từ ​​cuộc thảo luận này là UTF-8 có thể mã hóa tất cả các điểm hiện được xác định trong tiêu chuẩn Unicode và có khả năng sẽ làm được như vậy trong một thời gian tới.
Tên hiển thị
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.