U + 10FFFC là một điểm mã Unicode, nhưng giao diện của string
không hiển thị một chuỗi mã Unicode trực tiếp. Giao diện của nó cho thấy một chuỗi các đơn vị mã UTF-16. Đó là chế độ xem văn bản rất thấp. Thật không may là một cái nhìn mức độ thấp của văn bản được ghép vào giao diện rõ ràng và trực quan nhất có sẵn ... Tôi sẽ cố gắng không rant nhiều về cách tôi không thích thiết kế này, và chỉ nói rằng không quan trọng thật không may, nó chỉ là một thực tế (buồn) bạn phải sống với.
Trước hết, tôi sẽ đề xuất sử dụng char.ConvertFromUtf32
để nhận chuỗi ban đầu của bạn. đơn giản hơn nhiều, nhiều hơn nữa có thể đọc được:
var s = char.ConvertFromUtf32(0x10FFFC);
Vì vậy, của chuỗi Length
đây không phải là 1, bởi vì, như tôi đã nói, các thỏa thuận giao diện trong UTF-16 đơn vị mã, không điểm mã Unicode. U + 10FFFC sử dụng hai đơn vị mã UTF-16, vì vậy s.Length
là 2. Tất cả các điểm mã trên U + FFFF đều yêu cầu hai đơn vị mã UTF-16 để trình bày.
Bạn nên lưu ý rằng ConvertFromUtf32
không trả lại char
: char
là đơn vị mã UTF-16, không phải là điểm mã Unicode. Để có thể trả về tất cả các điểm mã Unicode, phương thức đó không thể trả về một đơn char
. Đôi khi nó cần phải trả lại hai, và đó là lý do tại sao nó làm cho nó một chuỗi. Đôi khi bạn sẽ tìm thấy một số API giao dịch trong int
s thay vì char
vì int
có thể được sử dụng để xử lý tất cả các điểm mã quá (đó là những gì ConvertFromUtf32
lấy làm đối số và số ConvertToUtf32
là kết quả).
string
thực hiện IEnumerable<char>
, có nghĩa là khi bạn lặp lại trên string
bạn sẽ nhận được một đơn vị mã UTF-16 cho mỗi lần lặp lại. Đó là lý do tại sao lặp lại chuỗi của bạn và in nó ra mang lại một số sản lượng bị hỏng với hai "thứ" trong đó. Đó là hai đơn vị mã UTF-16 tạo nên sự đại diện của U + 10FFFC.Chúng được gọi là "người thay thế". Người đầu tiên là người thay thế cao/người đứng đầu và người thứ hai là người đại diện thấp/thay thế. Khi bạn in chúng riêng lẻ, chúng không tạo ra đầu ra có ý nghĩa bởi vì người thay thế đơn lẻ thậm chí không hợp lệ trong UTF-16, và chúng cũng không được coi là ký tự Unicode.
Khi bạn nối hai người thay thế đó vào chuỗi trong vòng lặp, bạn sẽ tái tạo lại cặp thay thế một cách hiệu quả và in cặp đó sau làm cho bạn kết quả phù hợp.
Và ở mặt trước ranting, hãy lưu ý rằng không có gì phàn nàn rằng bạn đã sử dụng trình tự UTF-16 không đúng định dạng trong vòng lặp đó. Nó tạo ra một chuỗi với một đại diện duy nhất, và tất cả mọi thứ tiếp tục như không có gì xảy ra: loại string
thậm chí không phải là loại cũng được hình thành chuỗi đơn vị mã UTF-16, nhưng loại bất kỳ UTF-16 chuỗi đơn vị mã.
The char
structure cung cấp phương pháp tĩnh để đối phó với những người đại diện: IsHighSurrogate
, IsLowSurrogate
, IsSurrogatePair
, ConvertToUtf32
, và ConvertFromUtf32
. Nếu bạn muốn, bạn có thể viết một iterator rằng lặp trên các ký tự Unicode thay vì UTF-16 đơn vị mã:
static IEnumerable<int> AsCodePoints(this string s)
{
for(int i = 0; i < s.Length; ++i)
{
yield return char.ConvertToUtf32(s, i);
if(char.IsHighSurrogate(s, i))
i++;
}
}
Sau đó, bạn có thể lặp lại như:
foreach(int codePoint in s.AsCodePoints())
{
// do stuff. codePoint will be an int will value 0x10FFFC in your example
}
Nếu bạn muốn nhận được mỗi điểm mã như một chuỗi thay vì thay đổi kiểu trả về để IEnumerable<string>
và dòng năng suất để:
yield return char.ConvertFromUtf32(char.ConvertToUtf32(s, i));
với phiên bản này, các công việc sau như-là:
foreach(string codePoint in s.AsCodePoints())
{
Console.WriteLine(codePoint);
}
System.Globalization.StringInfo là cách để thực hiện. Phần còn lại của mã không chính xác. Có một cái nhìn tại: https://msdn.microsoft.com/en-us/library/system.globalization.stringinfo(v=vs.110).aspx – X181
Nó không phải là rõ ràng những gì bạn có ý nghĩa. Có vấn đề với mã từ câu trả lời này không? –