Używanie normalizacji Unicode do reprezentowania ciągów
Aplikacje mogą używać formatu Unicode do reprezentowania ciągów w wielu formularzach. W miarę wzrostu akceptacji Unicode, zwłaszcza za pośrednictwem Internetu, pojawiła się potrzeba wyeliminowania nieistotnych różnic w ciągach Unicode. Wiele reprezentacji kombinacji znaków komplikuje działanie oprogramowania, na przykład gdy serwer WWW odpowiada na żądanie strony lub gdy linker poszukuje określonego identyfikatora w bibliotece.
Ostrożność
Różne ciągi Unicode mogą być wizualnie identyczne, co budzi obawy dotyczące zabezpieczeń. Aby uzyskać więcej informacji, zobacz Zagadnienia dotyczące zabezpieczeń: Funkcje międzynarodowe.
W odpowiedzi na to wymaganie konsorcjum Unicode zdefiniowało proces o nazwie "normalizacja", który tworzy jedną reprezentację binarną dla dowolnej z równoważnych reprezentacji binarnych znaku. Po normalizacji dwa ciągi są równoważne, jeśli i tylko wtedy, gdy mają identyczne reprezentacje binarne. Normalizacja eliminuje pewne różnice, ale zachowuje wielkość liter.
Aby użyć normalizacji Unicode, aplikacja może wywołać funkcje NormalizeString i IsNormalizedString do zmieniania kolejności ciągów zgodnie z Unicode 4.0 TR#15. Normalizacja może pomóc zwiększyć bezpieczeństwo, zmniejszając alternatywne reprezentacje ciągów, które mają takie samo znaczenie językowe. Pamiętaj jednak, że normalizacja nie może całkowicie wyeliminować alternatywnych reprezentacji.
Aby uzyskać szczegółowy opis standardów Unicode dotyczących normalizacji, zobacz Standard Annex #15: Unicode Normalization Forms (UAX #15).
Ostrożność
Ponieważ normalizacja może zmienić formę ciągu, mechanizmy zabezpieczeń lub algorytmy weryfikacji znaków powinny być zwykle implementowane po normalizacji. Aby uzyskać więcej informacji, zobacz Zagadnienia dotyczące zabezpieczeń: Funkcje międzynarodowe.
Podaj wiele reprezentacji tego samego ciągu
W wielu przypadkach Unicode umożliwia wiele reprezentacji tego samego ciągu, lingwistycznie rzecz biorąc. Na przykład:
- Wielka litera A z umlautem może być przedstawiona jako pojedynczy punkt kodu Unicode "Ä" (U+00C4) lub jako kombinacja wielkiej litery A i znaku diakrytycznego ("A" + "¨", czyli U+0041 U+0308). Podobne zagadnienia dotyczą wielu innych znaków ze znakami diakrytycznymi.
- Wielka litera A może być reprezentowana w zwykły sposób (wielka litera łacińska A, U+0041) lub jako pełnoszeroka wielka litera łacińska A (U+FF21). Podobne zagadnienia dotyczą innych prostych liter łacińskich (zarówno wielkich, jak i małych) oraz znaków katakana używanych podczas pisania w języku japońskim.
- Ciąg "fi" może być reprezentowany przez znaki "f" i "i" (U+0066 U+0069) lub przez ligaturę "fi" (U+FB01). Podobne zagadnienia dotyczą wielu innych kombinacji znaków, dla których Unicode definiuje ligatury.
Korzystanie z czterech zdefiniowanych formularzy normalizacji
Aplikacje mogą przeprowadzać normalizację Unicode przy użyciu kilku algorytmów nazywanych "formularzami normalizacji", które przestrzegają różnych reguł. Konsorcjum Unicode zdefiniowało cztery formularze normalizacji: NFC (formularz C), NFD (formularz D), NFKC (formularz KC) i NFKD (formularz KD). Każda forma eliminuje pewne różnice, ale zachowuje wielkość liter. Win32 i .NET Framework obsługują wszystkie cztery formularze normalizacji.
Typ wyliczenia NLS NORM_FORM obsługuje cztery standardowe formularze normalizacji Unicode. Formularze C i D udostępniają kanoniczne formularze dla ciągów. Formy inne niż kanoniczne KC i KD zapewniają dalszą zgodność i mogą ujawnić pewne równoważności semantyczne, które nie są widoczne w formach C i D. Jednak robią to kosztem pewnej utraty informacji i ogólnie nie powinny być używane jako kanoniczny sposób przechowywania ciągów.
Z dwóch form kanonicznych forma C jest formą "skomponowaną", a forma D jest formą "rozłożoną". Na przykład, formularz C używa pojedynczego punktu kodu Unicode "Ä" (U+00C4), podczas gdy formularz D używa ("A" + "¨", czyli U+0041 U+0308). Są one renderowane identycznie, ponieważ znak "¨" (U+0308) jest znakiem łączącym. Formularz D może używać dowolnej liczby punktów kodu do reprezentowania pojedynczego punktu kodu używanego przez formularz C.
Jeśli dwa ciągi są identyczne w postaci C lub D, są identyczne w innej postaci. Ponadto w przypadku poprawnego renderowania są one wyświetlane w sposób nieodróżnialny od siebie i z oryginalnego nienormalizowanego ciągu.
Po normalizacji ciągi nie mogą być stale zwracane do ich oryginalnej reprezentacji. Jeśli na przykład ciąg, który zawiera mieszankę złożonych i rozłożonych reprezentacji znaków, jest konwertowany na znormalizowaną formę, nie ma możliwości przywrócenia go do oryginalnego, mieszanego ciągu. W związku z tym jeśli aplikacja wymaga oryginalnej reprezentacji ciągu, musi jawnie przechowywać te reprezentacje. Jednak konwersja między dwiema formami kanonicznymi jest odwracalna. Ciąg w postaci C można przekonwertować na formularz D, a następnie z powrotem na formularz C, a wynik jest identyczny z oryginalnym ciągiem formularza C.
Formularze KC i KD są podobne do formularzy C i D, ale te "formularze zgodności" mają dodatkowe mapowania znaków zgodnych do podstawowej formy każdego znaku. Takie mapowania mogą spowodować utratę drobnych odmian znaków. Łączą niektóre znaki, które wyróżniają się wizualnie. Na przykład łączą znaki o pełnej szerokości i połowie szerokości z tym samym znaczeniem semantycznym lub różnymi formami tej samej litery arabskiej lub ligaturą "fi" (U+FB01) i parą znaków "fi" (U+0066 U+0069). Łączą również niektóre znaki, które czasami mogą mieć inne znaczenie semantyczne, takie jak cyfra napisana jako indeks górny, jako indeks dolny lub ujęta w okręgu. Ze względu na tę utratę informacji formularze KC i KD zwykle nie powinny być używane jako kanoniczne formy ciągów, ale są przydatne w niektórych aplikacjach.
Formularz KC jest formularzem skomponowanym, a formularz KD jest formularzem rozłożonym. Aplikacja może przechodzić tam i z powrotem między formularzami KC i KD, ale nie ma spójnego sposobu przechodzenia z formularza KC lub KD z powrotem do oryginalnego ciągu, nawet jeśli oryginalny ciąg jest w postaci C lub D.
Systemy Windows, aplikacje firmy Microsoft i program .NET Framework zwykle generują znaki w postaci C przy użyciu normalnych metod wejściowych. Dla większości celów w systemie Windows formularz C jest preferowanym formularzem. Na przykład znaki w postaci C są generowane przez wprowadzanie klawiatury systemu Windows. Jednak znaki importowane z sieci Web i innych platform mogą wprowadzać inne formy normalizacji do strumienia danych.
Poniższe przykłady pochodzą z języka UAX #15 i ilustrują różnice między czterema formami normalizacji.
Oryginał | Formularz D | Formularz C | Notatki |
---|---|---|---|
"Äffin" | "Ffin\u0308" | "Äffin" | ffi_ligature (U+FB03) nie jest rozłożona na pojedyncze znaki, ponieważ ma mapowanie zgodności, a nie mapowanie kanoniczne. |
Ä\uFB03n | "A\u0308\uFB03n" | Ä\uFB03n | |
"Henry IV" | "Henry IV" | "Henry IV" | NUMER RZYMSKI IV (U+2163) nie jest rozłożony.${REMOVE}$ |
Henry \u2163 | Henry \u2163 | "Henry \u2163" | |
Ga | ka +dziesięć | Ga | Różne odpowiedniki zgodności pojedynczego japońskiego znaku nie powodują wystąpienia tego samego ciągu w postaci C.${REMOVE}$ |
ka +dziesięć | ka +10 | Ga | |
hw_ka +hw_ten | hw_ka +hw_ten | hw_ka +hw_ten | |
ka +hw_ten | ka +hw_ten | ka +hw_ten | |
hw_ka +dziesięć | hw_ka +dziesięć | hw_ka +dziesięć | |
kaks | k i + a ₘ + ks f | kaks | Sylaby hangul są zachowywane podczas normalizacji. |
Oryginał | Formularz KD | Formularz KC | Notatki |
---|---|---|---|
"Äffin" | "Ffin\u0308" | "Äffin" | Ffi_ligature (U+FB03) jest rozłożona w postaci KC, ale nie w postaci C.${REMOVE}$ |
"Ä\uFB03n" | "Ffin\u0308" | "Äffin" | |
"Henry IV" | "Henry IV" | "Henry IV" | Wynikowe ciągi są identyczne w postaci KC.${REMOVE}$ |
Henry \u2163 | "Henry IV" | "Henry IV" | |
Ga | ka +dziesięć | Ga | Różne wersje zgodne pojedynczego japońskiego znaku skutkują tym samym ciągiem w postaci KC.${REMOVE}$ |
ka +ten | ka plus dziesięć | Ga | |
hw_ka +hw_ten | ka +dziesięć | Ga | |
ka +hw_ten | ka +dziesięć | Ga | |
hw_ka +dziesięć | ka + dziesięć | Ga | |
kaks | k i + m + ks f | kaks | Sylaby hangul są zachowywane podczas normalizacji. We wcześniejszych wersjach Unicode znaki jamo, takie jak ks f, miały przypisania zgodności do k f + s f. Te mapowania zostały usunięte w standardze Unicode 2.1.9, aby upewnić się, że są obsługiwane sylaby Hangul. |
Notatka
Obie powyższe tabele mają prawa autorskie do © 1998-2006 Unicode, Inc. Wszelkie prawa zastrzeżone.
Używanie form skomponowanych dla pojedynczych glifów
Wiele sekwencji znaków, które odpowiadają pojedynczemu glifowi, nie mają składanych form. Nawet w przypadku normalizacji według formularza C pojedynczy wizualny symbol glyph lub logiczny element tekstowy może składać się z wielu punktów kodu Unicode. Na przykład kilka znaków używanych na piśmie litewskich ma podwójne znaki diakrytyczne, ponieważ mają tylko rozłożone formy. Przykładem jest małe litery U z macronem i tyldą ("ū̃", U+016b U+0303, gdzie pierwszy punkt kodu jest małymi literami U z macronem, a drugi jest połączeniem ostrego akcentu).
Przykład
Odpowiedni przykład można znaleźć w NLS: Przykład normalizacji Unicode.
Tematy pokrewne