[java] Java에서 “대리 쌍”이란 무엇입니까?
에 대한 설명서 StringBuffer
, 특히 reverse () 메서드 를 읽고있었습니다 . 이 문서에는 서로 게이트 쌍 에 대해 언급되어 있습니다. 이 맥락에서 대리 쌍은 무엇입니까? 그리고 무엇 낮은 및 높은 대리는?
답변
“서로 게이트 쌍”이라는 용어는 UTF-16 인코딩 체계에서 높은 코드 포인트로 유니 코드 문자를 인코딩하는 수단을 의미합니다.
유니 코드 문자 인코딩에서 문자는 0x0과 0x10FFFF 사이의 값에 매핑됩니다.
내부적으로 Java는 UTF-16 인코딩 체계를 사용하여 유니 코드 텍스트 문자열을 저장합니다. UTF-16에서는 16 비트 (2 바이트) 코드 단위가 사용됩니다. 16 비트는 0x0에서 0xFFFF까지의 문자 범위 만 포함 할 수 있으므로이 범위 (0x10000에서 0x10FFFF) 이상의 값을 저장하는 데 약간의 추가 복잡성이 사용됩니다. 이것은 서로 게이트로 알려진 코드 단위 쌍을 사용하여 수행됩니다.
대리 코드 단위는 두 코드 단위 시퀀스의 시작 또는 끝에 허용되는지에 따라 “고 대리자”및 “저 대리자”로 알려진 두 범위에 있습니다.
답변
초기 Java 버전은 16 비트 char 데이터 유형을 사용하여 유니 코드 문자를 나타냅니다. 모든 유니 코드 문자의 값은 65,535 (0xFFFF)보다 작고 16 비트로 표현 될 수 있기 때문에이 디자인은 당시에 의미가있었습니다. 그러나 나중에 유니 코드는 최대 값을 1,114,111 (0x10FFFF)로 늘 렸습니다. 16 비트 값이 너무 작아서 유니 코드 버전 3.1에서 모든 유니 코드 문자를 표시 할 수 없으므로 UTF-32 인코딩 체계에 코드 포인트라고하는 32 비트 값이 채택되었습니다. 그러나 효율적인 메모리 사용을 위해서는 16 비트 값이 32 비트 값보다 선호되므로 유니 코드는 16 비트 값을 계속 사용할 수 있도록 새로운 디자인을 도입했습니다. UTF-16 인코딩 체계에서 채택 된이 디자인은 1,024 개의 값을 16 비트 높은 대리자 (U + D800-U + DBFF 범위)에 할당하고 다른 1,024 개의 값은 16 비트의 낮은 대리자 (U + DC00 범위)에 할당합니다. U + DFFF로).
답변
그 문서에서 말하는 것은 유효하지 않은 UTF-16 문자열은 reverse
유효한 문자열의 반대 일 수 있기 때문에 메소드를 호출 한 후에 유효해질 수 있다는 것입니다. 서로 게이트 쌍 ( 여기서 설명 )은 단일 유니 코드 코드 포인트를 인코딩하는 UTF-16의 16 비트 값 쌍입니다. 낮고 높은 대리모는 그 인코딩의 두 반쪽입니다.
답변
이 게시물 의 위 답변에 더 많은 정보를 추가하십시오 .
Java-12에서 테스트되었으며 5 이상의 모든 Java 버전에서 작동합니다.
여기에 언급 된 바와 같이 : https://stackoverflow.com/a/47505451/2987755 ,
어느 문자 (유니 코드가 U + FFFF보다 높음)는 대리 쌍으로 표시되며 Java는 문자 값 쌍, 즉 단일 유니 코드로 저장됩니다. 문자는 두 개의 인접한 Java 문자로 표시됩니다.
다음 예제에서 볼 수 있듯이
1. 길이 :
"?".length() //2, Expectations was it should return 1
"?".codePointCount(0,"?".length()) //1, To get the number of Unicode characters in a Java String
2. 평등 : 아래와 같이
유니 코드 \ud83c\udf09
를 사용하여 “?”를 문자열로 나타내고 평등을 확인하십시오.
"?".equals("\ud83c\udf09") // true
Java는 UTF-32를 지원하지 않습니다
"?".equals("\u1F309") // false
3. 유니 코드 문자를 Java 문자열로 변환 할 수 있습니다
"?".equals(new String(Character.toChars(0x0001F309))) //true
4. String.substring ()은 보충 문자를 고려하지 않습니다
"??".substring(0,1) //"?"
"??".substring(0,2) //"?"
"??".substring(0,4) //"??"
이를 해결하기 위해 우리는 사용할 수 있습니다 String.offsetByCodePoints(int index, int codePointOffset)
"??".substring(0,"??".offsetByCodePoints(0,1) // "?"
"??".substring(2,"??".offsetByCodePoints(1,2)) // "?"
5. 순회 유니 코드 문자열 의 BreakIterator
유니 코드 6. 정렬 문자열 java.text.Collator
7. 문자의 toUpperCase()
, toLowerCase()
, 방법은 사용하지 말아야 대신 사용하는 문자열 대문자와 특정 로케일의 소문자.
8. Character 클래스의 각 메소드에 대해 Character.isLetter(char ch)
더 나은 사용법을 지원하지 않으므로 보충 문자를 처리 할 수 있는 유형 이 있습니다.
의 캐릭터 세트를 지정 9. 문자열을 바이트로 변환,, ,Character.isLetter(int codePoint)
methodName(char ch)
methodName(int codePoint)
String.getBytes()
InputStreamReader
OutputStreamWriter
참조 :
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
예제 image1 image2 에 대한 추가 정보
탐색해야 할 다른 용어 : Normalization , BiDi
답변
대리 쌍은 UTF-16의 특정 문자 인코딩 방식을 나타냅니다 ( http://en.wikipedia.org/wiki/UTF-16/UCS-2#Code_points_U.2B10000..U.2B10FFFF 참조) .
답변
작은 서문
- 유니 코드는 코드 포인트를 나타냅니다. 각 코드 포인트는 유니 코드 표준에 따라 8 비트, 16 비트 또는 32 비트 블록으로 인코딩 될 수 있습니다.
-
버전 3.1 이전에는 주로 UTF-8로 알려진 8 비트 인코딩과 UCS-2 또는 “2 옥텟으로 코딩 된 범용 문자 세트”로 알려진 16 비트 인코딩이 사용되었습니다. UTF-8은 유니 코드 포인트를 1 바이트 블록 시퀀스로 인코딩하는 반면 UCS-2는 항상 2 바이트를 사용합니다.
A = 41 -UTF-8을 사용하는 8 비트 블록 1 개
의 A = 0041 -UCS-2
Ω 의 16 비트 블록 1 개 = CE A9 -UTF-8
Ω 의 8 비트 블록 2 개 = 03A9-1 개의 블록 UCS-2를 사용한 16 비트
문제
컨소시엄은 16 비트가 사람이 읽을 수있는 언어를 포함하기에 충분하다고 생각하여 2 ^ 16 = 65536의 코드 값을 제공합니다. BPM 또는 Basic Multilingual Plane으로도 알려진 Plane 0에는 오늘날 65536 개의 코드 포인트 중 55,445가 포함되어 있습니다. BPM은 중국어-일본어-한국어 기호 (CJK)를 포함하여 세계의 거의 모든 인간 언어를 다룹니다.
시간이 지났고 새로운 아시아 문자 집합이 추가되었고 중국어 기호는 7 만 점 이상을 차지했습니다. 이제 표준 ?의 일부로 이모티콘 포인트 도 있습니다. 새로운 16 개의 “추가” 비행기 가 추가되었습니다. UCS-2 공간은 Plane-0보다 큰 것을 덮기에 충분하지 않았습니다.
유니 코드 결정
- 유니 코드를 비행기 당 17 개의 비행기 × 65 536 자로 제한 = 1114112 최대 포인트.
- 각 코드 포인트에 대해 32 비트를 유지하고 모든 평면을 커버하기 위해 이전 UCS-4로 알려진 UTF-32를 제공합니다.
- UTF-8을 동적 인코딩으로 계속 사용하고 각 코드 포인트에 대해 UTF-8을 최대 4 바이트로 제한하십시오 (예 : 포인트 당 1-4 바이트).
- UCS-2 지원 중단
-
UCS-2를 기반으로 UTF-16을 작성하십시오. UTF-16을 동적으로 설정하면 포인트 당 2 바이트 또는 4 바이트가 필요합니다. High Surrogates라는 1,024 개의 U + D800–U + DBFF를 UTF-16에 할당합니다. Low Surrogates라는 1024 개의 심볼 U + DC00–U + DFFF를 UTF-16에 할당합니다.
이러한 변경 사항으로 인해 BPM은 UTF-16에서 16 비트의 1 블록으로 처리되는 반면 모든 “보충 문자”는 2 개의 블록을 각각 16 비트 씩 표시하는 대리 쌍 ( 전체 1024×1024 = 1,048 576 포인트)으로 처리됩니다.
높은 대리가 낮은 대리보다 우선합니다 . 이 규칙에서 벗어난 것은 잘못된 인코딩으로 간주됩니다. 예를 들어, 쌍이없는 서로 게이트는 정확하지 않고 높은 서로 게이트 앞에서는 낮은 서로 게이트가 올바르지 않습니다.
M ‘MUSICAL SYMBOL G CLEF’는
UTF-32에서
0xD0 0x9D 0x84 0x9E (4 x 1 바이트)와 같은 한 쌍의 서로 게이트 0xD834 0xDD1E (2 x 2 바이트)로 UTF-16으로 인코딩
됩니다. 0x0001D11E (1 x 4 바이트).
현재 상황
- 표준에 따르면 서로 게이트는 UTF-16에만 구체적으로 할당되지만 역사적으로 일부 Windows 및 Java 응용 프로그램은 이제 서로 게이트 범위로 예약 된 UTF-8 및 UCS-2 포인트를 사용했습니다.
잘못된 UTF-8 / UTF-16 인코딩으로 레거시 응용 프로그램을 지원하기 위해 새로운 표준 WTF-8 인 Wobbly Transformation Format이 작성되었습니다. 쌍을 이루지 않은 서로 게이트 또는 잘못된 시퀀스와 같은 임의의 서로 게이트 지점을 지원합니다. 오늘날 일부 제품은 표준을 준수하지 않고 UTF-8을 WTF-8로 취급합니다. - 대리 솔루션 은 서로 다른 인코딩 간 변환시 많은 보안 문제를 발생 시켰으며 대부분은 잘 처리되었습니다.
⚖ 주제를 따르기 위해 많은 역사적 세부 사항이 억제되었습니다.
최신 유니 코드 표준은 http://www.unicode.org/versions/latest 에서 찾을 수 있습니다 .
답변
서로 게이트 쌍은 UTF-16에서 하나의 ‘코드 포인트’를 구성하는 두 개의 ‘코드 단위’입니다. Java 문서는 이러한 ‘코드 포인트’가 여전히 유효하고 반대로 ‘코드 단위’가 올바르게 주문되었다고 명시하고 있습니다. 또한 두 개의 짝을 이루지 않은 서로 게이트 코드 단위가 반대로되어 유효한 서로 게이트 쌍을 형성 할 수 있다고 명시되어 있습니다. 즉, 짝을 이루지 않은 코드 단위가 있으면 반대의 반대가 동일하지 않을 가능성이 있습니다!
그러나이 문서는 Graphemes에 대해 아무 것도 말하지 않습니다. 여러 코드 포인트가 결합되어 있습니다. 이는 e와 그에 따른 악센트가 여전히 전환 될 수 있음을 의미하므로 e 앞에 악센트를 배치합니다. 즉, e 앞에 다른 모음이 있으면 e에 있던 악센트가 생길 수 있습니다.
이케!
