Programing

정규화 된 UTF-8이란 무엇입니까?

crosscheck 2020. 7. 10. 08:01
반응형

정규화 된 UTF-8이란 무엇입니까?


ICU 프로젝트는 (또한 지금 갖고있는 PHP 라이브러리를 ) 검색 할 때 쉽게 값을 비교할 수 있도록 도움 정규화 UTF-8 문자열에 필요한 클래스가 포함되어 있습니다.

그러나 이것이 응용 프로그램에 대한 의미알아 내려고 노력 중 입니다. 예를 들어 어떤 경우에 "호환성 동등성"대신 "정식 동등성"을 원하십니까?


유니 코드 정규화에 대해 알고 싶지 않은 모든 것

정식 정규화

유니 코드에는 일부 문자 (가장 두드러진 강조 문자)를 인코딩하는 여러 가지 방법이 있습니다. 표준 정규화는 코드 포인트를 표준 인코딩 형식으로 변경합니다. 결과 코드 포인트는 글꼴 또는 렌더링 엔진의 버그를 제외하고 원래 코드 포인트와 동일하게 나타납니다.

사용시기

결과가 동일하게 표시되므로 입력과 비트가 동일하지 않은 결과를 허용하지 않는 한 문자열을 저장하거나 표시하기 전에 표준 정규화를 문자열에 적용하는 것이 항상 안전합니다.

정식 정규화는 NFD와 NFC의 두 가지 형태로 제공됩니다. 이 두 형식은 손실없이 두 형식간에 변환 할 수 있다는 점에서 동일합니다. NFC에서 두 문자열을 비교하면 항상 NFD에서 비교하는 것과 동일한 결과를 얻을 수 있습니다.

NFD

NFD는 문자가 완전히 확장되었습니다. 이것은 계산하는 가장 빠른 정규화 형식이지만 결과적으로 더 많은 코드 포인트가 생성됩니다 (예 : 더 많은 공간 사용).

아직 정규화되지 않은 두 문자열을 비교하려는 경우 호환성 정규화가 필요하다는 것을 알지 않는 한 이것이 선호되는 정규화 양식입니다.

NFC

NFC는 NFD 알고리즘을 실행 한 후 가능하면 코드 포인트를 재결합합니다. 시간이 조금 더 걸리지 만 줄이 짧아집니다.

호환성 정규화

유니 코드에는 실제로 속하지는 않지만 레거시 문자 집합에 사용 된 많은 문자가 포함됩니다. 유니 코드는 이러한 문자 집합의 텍스트를 유니 코드로 처리 한 다음 손실없이 다시 변환 할 수 있도록하기 위해 추가했습니다.

호환성 정규화는 이들을 대응하는 "실제"문자 시퀀스로 변환하고 표준 정규화도 수행합니다. 호환성 정규화 결과가 원본과 동일하게 나타나지 않을 수 있습니다.

서식 정보가 포함 된 문자는 그렇지 않은 문자로 바뀝니다. 예를 들어 문자 는로 변환됩니다 9. 다른 것들은 서식 차이를 포함하지 않습니다. 예를 들어 로마 숫자 문자 는 일반 문자로 변환됩니다 IX.

분명히이 변환이 수행되면 더 이상 손실없이 원래 문자 세트로 다시 변환 할 수 없습니다.

사용시기

유니 코드 컨소시엄은 ToUpperCase변환 과 같은 호환성 정규화에 대한 생각을 제안 합니다. 그것은 어떤 상황에서는 유용 할 수 있지만, 단지 윌리-니 일로 적용해서는 안됩니다.

당신이 아마 9일치 하는 검색을 원할 것이기 때문에 훌륭한 사용 사례는 검색 엔진이 될 것입니다 .

호환성 정규화를 사용자에게 적용한 결과를 표시하지 않아야 할 수도 있습니다.

NFKC / NFKD

호환성 정규화 양식은 NFKD와 NFKC의 두 가지 형태로 제공됩니다. 그들은 NFD와 C와 같은 관계를 가지고 있습니다.

NFKC의 모든 문자열은 본질적으로 NFC에도 있으며 NFKD 및 NFD의 경우에도 동일합니다. 따라서 NFKD(x)=NFD(NFKC(x)), NFKC(x)=NFC(NFKD(x))

결론

의심스러운 경우 표준 정규화를 사용하십시오. 적용 가능한 공간 / 속도 상충 관계 또는 상호 운용중인 항목에 필요한 사항에 따라 NFC 또는 NFD를 선택하십시오.


악센트가있는 문자 (예 :)와 같은 일부 문자 é는 단일 코드 포인트 U+00E9또는 일반 문자 다음에 결합 악센트 표시가 있는 두 가지 방법으로 표현할 수 있습니다 U+0065 U+0301. 보통의 정규화는 이들 중 하나를 항상 나타 내기 위해 선택할 것입니다 (NFC의 단일 코드 포인트, NFD의 결합 형태).

기본 시퀀스의 여러 시퀀스로 표시되고 마크를 조합 할 수있는 문자 (예 : "s, 아래 도트, 위 도트"대 vs. 도트 위의 도트 아래 또는 이미 도트 중 하나가있는 기본 문자 사용)의 경우 NFD는 또한 다음 중 하나를 선택하십시오 (아래에서 먼저 진행됨)

호환성 분해에는 "실제로는 안되는"문자이지만 레거시 인코딩에 사용 되었기 때문에 많은 문자가 포함됩니다. 일반적인 정규화는 이들을 통합하지 않습니다 (왕복 무결성을 유지하기 위해-레거시 인코딩 (소수의 베트남어 인코딩 제외)이 모두 사용되지 않기 때문에 결합 양식에는 문제가되지 않습니다). 그러나 호환성 정규화는 가능합니다. 일부 동아시아 인코딩 (또는 반자 / 전각 가타카나 및 알파벳) 또는 MacRoman의 "fi"합자에 나타나는 "kg"킬로그램 기호를 생각하십시오.

자세한 내용은 http://unicode.org/reports/tr15/ 를 참조하십시오.


Normal forms (of Unicode, not databases) deal primarily (exclusively?) with characters that have diacritical marks. Unicode provides some characters with "built in" diacritical marks, such as U+00C0, "Latin Capital A with Grave". The same character can be created from a `Latin Capital A" (U+0041) with a "Combining Grave Accent" (U+0300). That means even though the two sequences produce the same resulting character, a byte-by-byte comparison will show them as being completely different.

Normalization is an attempt at dealing with that. Normalizing assures (or at least tries to) that all the characters are encoded the same way -- either all using a separate combining diacritical mark where needed, or all using a single code point wherever possible. From a viewpoint of comparison, it doesn't really matter a whole lot which you choose -- pretty much any normalized string will compare properly with another normalized string.

In this case, "compatibility" means compatibility with code that assumes that one code point equals one character. If you have code like that, you probably want to use the compatibility normal form. Although I've never seen it stated directly, the names of the normal forms imply that the Unicode consortium considers it preferable to use separate combining diacritical marks. This requires more intelligence to count the actual characters in a string (as well as things like breaking a string intelligently), but is more versatile.

If you're making full use of ICU, chances are that you want to use the canonical normal form. If you're trying to write code on your own that (for example) assumes a code point equals a character, then you probably want the compatibility normal form that makes that true as often as possible.


If two unicode strings are canonically equivalent the strings are really the same, only using different unicode sequences. For example Ä can be represented either using the character Ä or a combination of A and ◌̈.

If the strings are only compatibility equivalent the strings aren't necessarily the same, but they may be the same in some contexts. E.g. ff could be considered same as ff.

So, if you are comparing strings you should use canonical equivalence, because compatibility equivalence isn't real equivalence.

But if you want to sort a set of strings it might make sense to use compatibility equivalence as the are nearly identical.


Whether canonical equivalence or compatibility equivalence is more relevant to you depends on your application. The ASCII way of thinking about string comparisons roughly maps to canonical equivalence, but Unicode represents a lot of languages. I don't think it is safe to assume that Unicode encodes all languages in a way that allows you to treat them just like western european ASCII.

Figures 1 and 2 provide good examples of the two types of equivalence. Under compatibility equivalence, it looks like the same number in sub- and super- script form would compare equal. But I'm not sure that solve the same problem that as the cursive arabic form or the rotated characters.

The hard truth of Unicode text processing is that you have to think deeply about your application's text processing requirements, and then address them as well as you can with the available tools. That doesn't directly address your question, but a more detailed answer would require linguistic experts for each of the languages you expect to support.


This is actually fairly simple. UTF-8 actually has several different representations of the same "character". (I use character in quotes since byte-wise they are different, but practically they are the same). An example is given in the linked document.

The character "Ç" can be represented as the byte sequence 0xc387. But it can also be represented by a C (0x43) followed by the byte sequence 0xcca7. So you can say that 0xc387 and 0x43cca7 are the same character. The reason that works, is that 0xcca7 is a combining mark; that is to say it takes the character before it (a C here), and modifies it.

Now, as far as the difference between canonical equivalence vs compatibility equivalence, we need to look at characters in general.

There are 2 types of characters, those that convey meaning through the value, and those that take another character and alter it. 9 is a meaningful character. A super-script ⁹ takes that meaning and alters it by presentation. So canonically they have different meanings, but they still represent the base character.

Canonical equivalence is where the byte sequence is rendering the same character with the same meaning. Compatibility equivalence is when the byte sequence is rendering a different character with the same base meaning (even though it may be altered). The 9 and ⁹ are compatibility equivalent since they both mean "9", but are not canonically equivalent since they don't have the same representation.


The problem of compare strings: two strings with content that is equivalent for the purposes of most applications may contain differing character sequences.

See Unicode's canonical equivalence: if the comparison algorithm is simple (or must be fast), the Unicode equivalence is not performed. This problem occurs, for instance, in XML canonical comparison, see http://www.w3.org/TR/xml-c14n

To avoid this problem... What standard to use? "expanded UTF8" or "compact UTF8"?
Use "ç" or "c+◌̧."?

W3C and others (ex. file names) suggest to use the "composed as canonical" (take in mind C of "most compact" shorter strings)... So,

The standard is C! in doubt use NFC

For interoperability, and for "convention over configuration" choices, the recommendation is the use of NFC, to "canonize" external strings. To store canonical XML, for example, store it in the "FORM_C". The W3C's CSV on the Web Working Group also recomend NFC (section 7.2).

PS: de "FORM_C" is the default form in most of libraries. Ex. in PHP's normalizer.isnormalized().


Ther term "compostion form" (FORM_C) is used to both, to say that "a string is in the C-canonical form" (the result of a NFC transformation) and to say that a transforming algorithm is used... See http://www.macchiato.com/unicode/nfc-faq

(...) each of the following sequences (the first two being single-character sequences) represent the same character:

  1. U+00C5 ( Å ) LATIN CAPITAL LETTER A WITH RING ABOVE
  2. U+212B ( Å ) ANGSTROM SIGN
  3. U+0041 ( A ) LATIN CAPITAL LETTER A + U+030A ( ̊ ) COMBINING RING ABOVE

These sequences are called canonically equivalent. The first of these forms is called NFC - for Normalization Form C, where the C is for compostion. (...) A function transforming a string S into the NFC form can be abbreviated as toNFC(S), while one that tests whether S is in NFC is abbreviated as isNFC(S).


Note: to test of normalization of little strings (pure UTF-8 or XML-entity references), you can use this test/normalize online converter.

참고URL : https://stackoverflow.com/questions/7931204/what-is-normalized-utf-8-all-about

반응형