Được rồi, trong .Net và C #, tất cả các chuỗi được mã hóa dưới dạng UTF-16LE . A string
được lưu trữ dưới dạng một chuỗi ký tự. Mỗi char
gói đóng gói lưu trữ 2 byte hoặc 16 bit.
Những gì chúng ta thấy "trên giấy hoặc màn hình" là một chữ cái, ký tự, glyph, ký hiệu hoặc dấu chấm câu có thể được coi là một thành phần văn bản duy nhất. Như được mô tả trong Phụ lục Unicode # 29 PHÂN TÍCH VĂN BẢN UNICODE , mỗi Phần tử Văn bản được biểu thị bằng một hoặc nhiều Điểm Mã. Một danh sách đầy đủ các Mã có thể được tìm thấy ở đây .
Mỗi Điểm Mã cần được mã hóa thành nhị phân để biểu diễn bên trong bằng máy tính. Như đã nêu, mỗi char
cửa hàng 2 byte. Mã điểm tại hoặc bên dưới U+FFFF
có thể được lưu trữ trong một char
. Điểm Mã ở trên U+FFFF
được lưu trữ dưới dạng cặp thay thế, sử dụng hai ký tự đại diện cho một Điểm Mã duy nhất.
Dựa vào những gì chúng ta biết bây giờ chúng ta có thể suy ra, một Phần tử văn bản có thể được lưu trữ dưới dạng một char
, như một cặp thay thế của hai ký tự hoặc, nếu Phần tử văn bản được biểu thị bằng nhiều Điểm mã kết hợp một số ký tự đơn và Cặp thay thế. Như thể điều đó không đủ phức tạp, một số Thành phần Văn bản có thể được biểu diễn bằng các kết hợp Điểm Mã khác nhau như được mô tả trong, Phụ lục Chuẩn Unicode # 15, HÌNH THỨC BÌNH LUẬN BÌNH LUẬN UNICODE .
Kết hợp
Vì vậy, các chuỗi trông giống nhau khi được kết xuất thực sự có thể được tạo thành từ một tổ hợp ký tự khác nhau. Một so sánh thứ tự (byte theo byte) của hai chuỗi như vậy sẽ phát hiện ra sự khác biệt, điều này có thể là bất ngờ hoặc không mong muốn.
Bạn có thể mã hóa lại chuỗi .Net. để họ sử dụng cùng một hình thức chuẩn hóa. Sau khi được chuẩn hóa, hai chuỗi có cùng các thành phần văn bản sẽ được mã hóa theo cùng một cách. Để làm điều này, sử dụng hàm string.N normalize . Tuy nhiên, hãy nhớ rằng, một số yếu tố văn bản khác nhau trông tương tự nhau. :-S
Vì vậy, tất cả điều này có nghĩa gì liên quan đến câu hỏi? Phần tử văn bản '𠈓'
được biểu thị bằng phần mở rộng chữ tượng hình thống nhất U + 20213 cjk b . Điều này có nghĩa là nó không thể được mã hóa thành một lần duy nhất char
và phải được mã hóa thành Cặp thay thế, sử dụng hai ký tự. Đây là lý do tại sao string b
một trong những char
lâu hơn đó string a
.
Nếu bạn cần tin cậy (xem cảnh báo), hãy đếm số lượng Thành phần Văn bản trong một string
bạn nên sử dụng
System.Globalization.StringInfo
lớp như thế này.
using System.Globalization;
string a = "abc";
string b = "A𠈓C";
Console.WriteLine("Length a = {0}", new StringInfo(a).LengthInTextElements);
Console.WriteLine("Length b = {0}", new StringInfo(b).LengthInTextElements);
đưa ra đầu ra,
"Length a = 3"
"Length b = 3"
như mong đợi.
Hãy cẩn thận
Việc triển khai .Net của Phân đoạn văn bản Unicode trong StringInfo
và TextElementEnumerator
các lớp nói chung sẽ hữu ích và, trong hầu hết các trường hợp, sẽ mang lại phản hồi mà người gọi mong đợi. Tuy nhiên, như đã nêu trong Phụ lục tiêu chuẩn Unicode # 29, "Mục tiêu phù hợp với nhận thức của người dùng không phải lúc nào cũng có thể được đáp ứng chính xác bởi vì văn bản không phải lúc nào cũng chứa đủ thông tin để quyết định ranh giới rõ ràng."