UTF-8이 인코딩에서 여러 비트를 낭비하는 이유 10xxxxxx x는이 비트가

Wikipedia 기사 에 따르면 UTF-8의 형식은 다음과 같습니다.

첫 번째 코드 마지막 코드 바이트 바이트 1 바이트 2 바이트 3 바이트 4
사용 된 포인트
U + 0000 U + 007F 1 0xxxxxxx
U + 0080 U + 07FF 2110xxxxx 10xxxxxx
U + 0800 U + FFFF 3 1110xxxx 10xxxxxx 10xxxxxx
U + 10000 U + 1FFFFF 4 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
x는이 비트가 코드 포인트를 선택하는 데 사용됨을 의미합니다.

이렇게하면 각 연속 바이트에서 2 비트와 첫 번째 바이트에서 1 비트가 낭비됩니다. UTF-8이 다음과 같이 인코딩되지 않은 이유는 무엇입니까?

첫 번째 코드 마지막 코드 바이트 바이트 1 바이트 2 바이트 3
사용 된 포인트
U + 0000 U + 007F 1 0xxxxxxx
U + 0080 U + 3FFF 2 10xxxxxx xxxxxxxx
U + 0800 U + 1FFFFF 3110xxxxx xxxxxxxx xxxxxxxx

코드 포인트가 기본 다국어 평면을 벗어나거나 코드 포인트가 [U + 800, U + 3FFF] 범위에있는 경우 1 바이트를 저장합니다.

UTF-8이 왜 더 효율적인 방식으로 인코딩되지 않습니까?



답변

다중 바이트 시퀀스 중간에있을 때이를 감지 할 수 있습니다. UTF-8 데이터를 볼 때, 당신은 당신이 보는 경우 알고 10xxxxxx, 당신은 멀티 바이트 문자의 중간에 있는지, 그리고 당신이 중 하나가 표시 될 때까지 스트림에 백업해야합니다 0xxxxxx11xxxxxx. 체계를 사용하면 바이트 2 또는 3은 쉽게 0xxxxxxx또는 같은 패터로 끝날 수 있습니다11xxxxxx

또한 저장되는 양은 인코딩하는 문자열 데이터의 종류에 따라 달라집니다. 대부분의 텍스트, 심지어 아시아 텍스트의 경우 일반 텍스트가있는 4 바이트 문자는 거의 볼 수 없습니다. 또한 텍스트가 어떻게 보일지에 대한 사람들의 순진한 추정은 종종 틀립니다. 일본어, 중국어 및 한국어 문자열을 포함하여 UTF-8로 현지화 된 텍스트가 있지만 실제로 대부분의 공간을 차지하는 것은 러시아어입니다. (아시아 문자열에는 종종 이름과 문장 부호 등으로 로마 문자가 산재되어 있기 때문에 평균 중국어 단어는 1 ~ 3 자이고 평균 러시아어 단어는 더 많기 때문에 더 많습니다.)


답변

공식적인 방법은 디코더가 튜플의 중간에있을 때 알리고 바이트가 0또는로 시작될 때까지 바이트를 건너 뛰거나 뒤로 이동하는 것을 알고 있습니다 11. 이것은 단일 바이트가 손상 될 때 가비지 값을 방지합니다.


답변

짧은 대답, 당신의 제안은 첫 바이트와 연속 바이트를 구별하지 않습니다.

첫 번째 바이트의 상단에있는 비트 패턴은 실제 문자가 몇 바이트 나 작성되는지 알려줍니다. 이러한 패턴은 문자열을 구문 분석하는 동안 오류 인식도 제공합니다. 문자의 (겉보기) 첫 바이트를 읽고 10xxxxxx를 얻는다면 동기화되지 않은 것입니다.


답변

언급되지 않은 것은 올바른 코드 포인트 시퀀스와 코드 포인트의 첫 번째 바이트를 가리키는 포인터가 UTF-8을 사용하면 첫 번째 바이트에 대한 포인터를 매우 쉽게 찾을 수 있다는 것입니다 이전 코드 포인트의 (01xx xxxx로 시작하는 모든 바이트 건너 뛰기) 인코딩을 사용하면 문자열의 시작 부분까지 모든 바이트를 검사하지 않으면 불가능합니다.

(2n + 2) 바이트의 시퀀스를 고려하십시오

0xxxxxxx
n times (10xxxxxx, 10xxxxxx)
0xxxxxxx

n times (10xxxxxx, 10xxxxxx)
(10xxxxxx, 0xxxxxxx)

이 시퀀스 다음에 첫 번째 코드 포인트의 첫 번째 바이트에 대한 포인터가있는 경우 모든 코드를 검사 하여 마지막 코드 포인트가 0xxxxxxx인지 (10xxxxxx, 0xxxxxxx)인지 확인 해야합니다 .

실제로는 이전 코드 포인트로 이동하는 것이 일정한 시간에 수행 될 수 있고 코드 포인트의 중간에 대한 포인터가 고정 될 수있는보다 효율적인 인코딩 체계가 있습니다. 다음 코드를 허용하십시오.

X where X < 128
YX where 128 ≤ Y < 236, X < 128
ZYY where 236 ≤ Z < 256, 0 ≤ Y < 236.

이전 3 바이트 중 하나가 236 이상이면 3 바이트 시퀀스의 시작입니다. 유효한 3 바이트 시퀀스 내에 2 바이트가있을 수 없기 때문입니다. 그렇지 않으면, 이전 2 바이트 중 하나가 ≥ 128 인 경우 2 바이트 시퀀스의 시작입니다. 그렇지 않으면 이전 바이트는 단일 바이트 <128입니다.

부분 문자열 검색이 약간 더 어려워집니다. 코드 포인트가 0 인 문자열에 0 바이트 만 포함되도록 0 바이트를 제외 할 수 있습니다.


답변