Czytałem dokumentację StringBuffer
, w szczególności metodę reverse () . Ta dokumentacja wspomina coś o parach zastępczych . Co to jest para zastępcza w tym kontekście? A czym są niskie i wysokie surogaty?
java
unicode
utf-16
surrogate-pairs
Raymond
źródło
źródło
String
aby składał się z nich, a nie tylko z jednostek char. Szkoda, że Java nie pozwala na użycie OO, aby to naprawić, ale zarównoString
klasa, jak iStringBuffer
klasy zostałyfinal
izizowane. Powiedz, czy to nie eufemizm na określenie zabitych? :)Odpowiedzi:
Termin „para zastępcza” odnosi się do sposobu kodowania znaków Unicode z wysokimi punktami kodowymi w schemacie kodowania UTF-16.
W kodowaniu znaków Unicode znaki są mapowane na wartości z przedziału od 0x0 do 0x10FFFF.
Wewnętrznie Java używa schematu kodowania UTF-16 do przechowywania ciągów tekstu Unicode. W UTF-16 używane są 16-bitowe (dwubajtowe) jednostki kodu. Ponieważ 16 bitów może zawierać tylko zakres znaków od 0x0 do 0xFFFF, do przechowywania wartości powyżej tego zakresu (0x10000 do 0x10FFFF) używana jest dodatkowa złożoność. Odbywa się to za pomocą par jednostek kodu znanych jako surogaty.
Jednostki kodu zastępczego znajdują się w dwóch zakresach zwanych „dużymi surogatami” i „małymi surogatami”, w zależności od tego, czy są dozwolone na początku, czy na końcu sekwencji dwóch jednostek kodu.
źródło
Wczesne wersje Java reprezentowały znaki Unicode przy użyciu 16-bitowego typu danych char. Ten projekt miał sens w tamtym czasie, ponieważ wszystkie znaki Unicode miały wartości mniejsze niż 65 535 (0xFFFF) i mogły być reprezentowane w 16 bitach. Później jednak Unicode zwiększył wartość maksymalną do 1114111 (0x10FFFF). Ponieważ wartości 16-bitowe były zbyt małe, aby reprezentować wszystkie znaki Unicode w standardzie Unicode 3.1, wartości 32-bitowe - zwane punktami kodowymi - zostały przyjęte do schematu kodowania UTF-32. Jednak wartości 16-bitowe są preferowane zamiast wartości 32-bitowych w celu efektywnego wykorzystania pamięci, dlatego Unicode wprowadził nowy projekt, aby umożliwić dalsze używanie wartości 16-bitowych. Ten projekt, przyjęty w schemacie kodowania UTF-16, przypisuje 1024 wartości do 16-bitowych wysokich surogatów (w zakresie U + D800 do U + DBFF), a kolejne 1024 wartości do 16-bitowych niskich surogatów (w zakresie U + DC00 do U + DFFF).
źródło
Dokumentacja mówi, że nieprawidłowe ciągi znaków UTF-16 mogą stać się poprawne po wywołaniu
reverse
metody, ponieważ mogą być one odwrotnością prawidłowych łańcuchów. Para zastępcza (omówiona tutaj ) to para 16-bitowych wartości w UTF-16, które kodują pojedynczy punkt kodowy Unicode; niskie i wysokie surogaty to dwie połowy tego kodowania.źródło
Dodanie więcej informacji do powyższych odpowiedzi z tego postu.
Testowany w Javie-12, powinien działać we wszystkich wersjach Java powyżej 5.
Jak wspomniano tutaj: https://stackoverflow.com/a/47505451/2987755 ,
którykolwiek znak (którego Unicode jest powyżej U + FFFF) jest reprezentowany jako para zastępcza, którą Java przechowuje jako parę wartości znaków, tj. Pojedynczy Unicode znak jest reprezentowany jako dwa sąsiednie znaki Java.
Jak widać na poniższym przykładzie.
1. Długość:
2. Równość:
Przedstaw "🌉" jako łańcuch znaków używając Unicode,
\ud83c\udf09
jak poniżej i sprawdź równość.Java nie obsługuje UTF-32
3. Możesz przekonwertować znak Unicode na ciąg Java
4. String.substring () nie uwzględnia znaków uzupełniających
Aby rozwiązać ten problem, możemy użyć
String.offsetByCodePoints(int index, int codePointOffset)
5. Ciąg Iteracja Unicode z BreakIterator
6. Sortowanie Struny z Unicode java.text.Collator
7. bohatera
toUpperCase()
,toLowerCase()
nie powinny być stosowane metody, zamiast, wielkie i małe litery użycie String poszczególnych lokalizacji.8.
Character.isLetter(char ch)
nie obsługuje, lepiej wykorzystywanychCharacter.isLetter(int codePoint)
, dla każdejmethodName(char ch)
metody w klasie Character zostanie określony typ,methodName(int codePoint)
który może obsługiwać dodatkowe znaki.9. Określ zestaw znaków w
String.getBytes()
, konwertując z bajtów na łańcuch,InputStreamReader
,OutputStreamWriter
Odniesienie:
https://coolsymbol.com/emojis/emoji-for-copy-and-paste.html#objects
https://www.online-toolz.com/tools/text-unicode-entities-convertor.php
https: //www.ibm.com/developerworks/library/j-unicode/index.html
https://www.oracle.com/technetwork/articles/javaee/supplementary-142654.html
Więcej informacji na temat przykładu image1 image2
Inne terminy, które warto poznać: Normalizacja , BiDi
źródło
Pary zastępcze odnoszą się do sposobu kodowania niektórych znaków w UTF-16, patrz http://en.wikipedia.org/wiki/UTF-16/UCS-2#Code_points_U.2B10000..U.2B10FFFF
źródło
Mała przedmowa
Przed wersją 3.1 najczęściej używane było kodowanie 8-bitowe, znane jako UTF-8, i kodowanie 16-bitowe, znane jako UCS-2 lub „Uniwersalny zestaw znaków zakodowany w 2 oktetach”. UTF-8 koduje punkty Unicode jako sekwencję bloków 1-bajtowych, podczas gdy UCS-2 zawsze zajmuje 2 bajty:
A = 41 - jeden blok 8-bitowy z UTF-8
A = 0041 - jeden blok 16-bitowy z UCS-2
Ω = CE A9 - dwa bloki 8-bitowe z UTF-8
Ω = 03A9 - jeden blok 16-bitowe z UCS-2
Problem
Konsorcjum uważało, że 16 bitów wystarczyłoby na pokrycie dowolnego języka czytelnego dla człowieka, co daje 2 ^ 16 = 65536 możliwych wartości kodu. Było to prawdą dla Plane 0, znanego również jako BPM lub Basic Multilingual Plane, który zawiera obecnie 55.445 z 65536 punktów kodowych. BPM obejmuje prawie każdy ludzki język na świecie, w tym symbole chińsko-japońsko-koreańskie (CJK).
Minął czas i dodano nowe azjatyckie zestawy znaków, same symbole chińskie zajęły ponad 70 000 punktów. Teraz są nawet w standardzie punkty Emoji 😺. Dodano nowe 16 „dodatkowych” samolotów . Pomieszczenie UCS-2 nie wystarczyło do pokrycia czegokolwiek większego niż Samolot-0.
Decyzja Unicode
Utwórz UTF-16 w oparciu o UCS-2. Uczyń UTF-16 dynamicznym, więc zajmuje 2 bajty lub 4 bajty na punkt. Przypisz 1024 punkty U + D800 – U + DBFF, zwane wysokimi surogatami, do UTF-16; przypisz 1024 symbole U + DC00 – U + DFFF, nazywane małymi surogatami, do UTF-16.
Z tymi zmianami, BPM jest pokryta 1 blokiem 16 bitów w UTF-16, podczas gdy wszystkie „znaki uzupełniające” są pokryte parami zastępczymi, które zawierają 2 bloki po 16 bitów każdy, łącznie 1024x1024 = 1 048 576 punktów.
Wysoki surogat poprzedza niski surogat . Każde odstępstwo od tej zasady jest uważane za złe kodowanie. Na przykład surogat bez pary jest niepoprawny, niski surogat stojący przed wysokim surogatem jest nieprawidłowy.
𝄞, 'MUSICAL SYMBOL G CLEF', jest zakodowany w UTF-16 jako para surogatów 0xD834 0xDD1E (2 na 2 bajty),
w UTF-8 jako 0xF0 0x9D 0x84 0x9E (4 na 1 bajt),
w UTF-32 jako 0x0001D11E (1 na 4 bajty).
Obecna sytuacja
Aby obsługiwać starsze aplikacje z nieprawidłowym kodowaniem UTF-8 / UTF-16, utworzono nowy standard WTF-8 , Wobbly Transformation Format. Obsługuje dowolne punkty zastępcze, takie jak niesparowany surogat lub niepoprawna sekwencja. Obecnie niektóre produkty nie są zgodne z normą i traktują UTF-8 jako WTF-8.
Aby podążać za tym tematem, usunięto wiele szczegółów historycznych ⚖.
Najnowszy standard Unicode można znaleźć pod adresem http://www.unicode.org/versions/latest
źródło
Para zastępcza to dwie „jednostki kodowe” w UTF-16, które tworzą jeden „punkt kodowy”. Dokumentacja Javy stwierdza, że te „punkty kodowe” będą nadal ważne, a ich „jednostki kodowe” będą poprawnie uporządkowane, po odwrotnej kolejności. Ponadto stwierdza, że dwie niesparowane jednostki kodu zastępczego mogą być odwrócone i tworzyć prawidłową parę zastępczą. Co oznacza, że jeśli istnieją niesparowane jednostki kodu, istnieje szansa, że odwrotna strona może nie być taka sama!
Zauważ jednak, że dokumentacja nie mówi nic o grafemach - które są połączonymi wieloma punktami kodowymi. Oznacza to, że e i akcent, który się z nim łączy, mogą być nadal przełączane, umieszczając w ten sposób akcent przed e. Co oznacza, że jeśli jest inna samogłoska przed e, może uzyskać akcent z e.
Yikes!
źródło