2017-11-23 24 views
2

는 최근 Tom Scott from Computerphile talk about UTF-8을 봤어 그 후에 연구의 비트는 UTF-8은 각 바이트에 대해 다음 헤더를 사용하여, 최대 6 바이트 문자를 인코딩 할 수 있습니다 이해 :언어가 UTF-8을 어떻게 표현합니까?

0xxx xxxx # 1 Byte character 
110x xxxx # 2 Byte character 
1110 xxxx # 3 Byte character 
1111 0xxx # 4 Byte character 
1111 10xx # 5 Byte character 
1111 110x # 6 Byte character 

그리고 여분의 바이트를 표현하기 위해 10xx xxxx을 사용했다. (나는 RFC3629가 이것을 단지 4 바이트까지만 제한한다는 것을 알고있다.)

그렇다면 2,164,286 개의 다른 문자가 인코딩 될 수 있음을 이해하면 (예약 된 문자 무시)?

이론적
0xxx xxxx # 7 bits      =>  128 
110x xxxx # 5 bits + 6 bits = 11 bits =>  2,048 
1110 xxxx # 4 bits + 6*2 bits = 16 bits => 65,536 
1111 0xxx # 3 bits + 6*3 bits = 21 bits => 2,097,152 
      #        == 2,164,864 

I은 ​​UTF-8 인코딩 문자열을 저장할 char 배열을 사용할 수도 있고, I 대신 UTF-32 등의 고정 길이 부호화를 사용할 수 있으며, 각 UTF 인코딩하는 등 unsigned long 어떤 4 바이트 타입을 사용 -8 인코딩 된 문자를 사용하지만 1 또는 2 바이트로 인코딩 된 UTF-8 문자 만 사용하는 텍스트의 경우 메모리가 크게 증가합니다. UTF-8 언어를 어떻게 캐릭터의 다양한 길이를 나타낼 수 있다면 (우리는 범위를 제한하는 C++를 할게요 내가 std::string 생각

이 UTF-8의 저장을 허용하고이 sizelength 반환 바이트 길이가됩니다 만, 이 질문의)이 문자를 내부적으로 인코딩합니다 (예 : std::string)?

+0

까지 및 변환을 담당하는 API가 있습니다. 예 :'MultiByteToWideChar'와'WideCharToMultiByte'. – Raindrop7

+0

@ Raindrop7은 사실 일지 모르지만 배경에서 무슨 일이 벌어지고 있는지에 대한 질문에 실제로 대답하지 않습니다. –

+0

올바른데, 유니 코드는 현재 21 비트 코드 포인트 만 허용합니다 (2^16 코드 포인트의 17 개 평면 만 실제로 가능합니다 지정된 32 중에서). –

답변

4

UTF-8 문자열은 몇 가지 제한 사항 (그래서 바이트하지 모든 순서는 유효한 UTF-8 문자열은 다음과 같은 일련의 바이트 (즉 char -s 또는 C uint8_t의입니다 ++)입니다, 당신은 몇 가지 문자열을 얻는 경우 UTF-8이라고 주장하는 바깥 쪽에서, 그것을 검증해야한다).

그래서 std::string -s를 사용하여 UTF-8 문자열을 나타낼 수 있습니다 (유효한 UTF-8 인 경우).

위에 UTF-8 라이브러리 (예 : libunistring 또는 Glib Unicode Manipulation)를 사용할 수 있습니다.

즉, UTF-8은 -s의 문자열 사용 방법에 관한 규칙으로 볼 수 있습니다. 물론

는, (예를 들어, std::stringsize()) 바이트 수 하지 UTF-8 문자 수 있음에 유의하십시오. 그리고 UTF-8 문자 (또는 해당 유니 코드)를 반복하기 위해 일반 반복자를 사용할 수 없습니다.

UTF-8 인식 C++ 라이브러리 (예 : Gtkmm의 경우 Glibmm ustring -s) 또는 유니 코드 문자열을 나타내는 라이브러리 (예 : QString -s, Qt)를 찾을 수 있습니다.

BTW, UTF-8 (및 유니 코드)은 화면이나 용지에서 제대로 렌더링하기에는 상당히 복잡합니다 (그래서 라이브러리가 필요합니다). 같은 문자열에 다양한 언어 (영어, 러시아어, 아랍어, 중국어)가 혼합되어있어 방향이 바뀌는 경우도 있습니다. 결합 문자 (악센트 등)가있을 수 있습니다. 유니 코드는 꽤 복잡합니다 (대부분의 인간의 언어를 모르기 때문에 대부분을 알지 못합니다. 영어, 프랑스어, 러시아어 만 말하고 읽을 수 있습니다.) 일부 그리스 문자를 해독 할 수 있습니다. 일부 히브리어 만 알고 있습니다. 그리고 중국은 완전히 내게 외국이다).

http://utf8everywhere.org/ 및 위키 피 케이션 UTF-8Unicode도 참조하십시오.

+1

그래서 만약에'std :: string'을 유효한 UTF-8을 저장하기 위해 사용했다면, 여전히 본질적으로 다른 데이터 타입보다는'char' 시퀀스로 저장 될 것입니다 (즉,'std : : string' ** 항상 ** 단지'char's의 순서를 저장합니까?)? –

+4

물론. 유니 코드 문자 (예 :'uint32_t ')를 사용할 수 있습니다. 당신은 아마 이것을하고 싶지 않을 것입니다. –

+0

그리고 유니 코드 "문자"를 하나의 "문자"로 결합하여 출력 할 수있는 웜이 있습니다. 예 é는 1 자 또는 2 자일 수 있습니다. –

3

C++ 표준은 올바른 UTF8 처리를 다루지 않지만 코드 포인트 (실제 문자, 바이트가 아닌)에 의해 문자열을 반복 할 수있는 라이브러리가 있습니다.

일반적으로 텍스트는 바이트 배열로 저장됩니다 (tagged pointer strings과 같은 호기심 최적화가 가능). 코드 포인트의 올바른 처리를 제공하는 경량 string views이 일반적으로 추가됩니다. 예 : Swift 프로그래밍 언어 employs this technique.

로서는

또는 I 대신 각 인코딩 UTF-32 등의 고정 길이 부호화를 사용하고 같은 부호 긴 임의 4 바이트 타입을 사용할 수 UTF을-8 문자

부호화

C++ 11은 이제 편의를 위해 std::u8string, std::u16stringstd::u32string을 제공합니다. wchar_t의 크기는 표준 정의가 아닌 컴파일러 정의이므로 이식 가능한 코드에서는 일반적으로 피해야하는 std::wstring도 있습니다.

2

올바른 지점으로 곧장 도착했습니다. C++은 UTF-8을 표현하지 않습니다. 내가 그것을 처리하지 않는다는 것을 알고 있습니다. 따라서 이것은 단지 관습 일 뿐이며 실제로 표현하는 컨벤션은 UTF-8을 생산하고 소비하는 컨벤션입니다.

이제 UTF-8은 바이트 배열을 나타내는 std :: string과 같은 C++의 도구를 사용할 수있는 바이트 주위를 지향한다고 말했듯이. 물론 표준을 인식하지 못하는 무작위 라이브러리에 문자열을 보내면 많은 일이 잘못 될 수 있습니다. 여기에있는 다른 대답에서 언급 한 문자열의 크기는 ASCII 문자가 아닌데도 문자가 1 바이트 이상이므로 이상한 행동을 유발할 가능성이 높습니다.

이제 UTF-8에 대한 좋은 점은 128 자까지의 모든 문자 (모든 영문 문자 포함)에 대해 동일한 표현을 가짐을 의미합니다. 이런 이유 때문에 문자열 제작자가 UTF-8을 인식하지 못하고 소비자가 사용하는 경우에는 문제가 계속 발생합니다.

이미이 작업을 수행 한 라이브러리가 많이 있으며 UTF-8 문자열에 대한 특수 유형을 제공하거나 std :: string을 UTF-8 문자열로 읽습니다. 표준 자체는 각 문자가 std::u8string, std::u16stringstd::u32string과 같이 1 바이트 이상일 수있는 문자열을 제공합니다.이 표준에서는 문자 크기가 다양하기 때문에 UTF-8의 경우 아무 것도 실제로 도움이되지 않습니다.

또한 네트워크를 통해 문자열을 통과 할 때 당신은 무엇을해야 다루이 주제에 대한 마지막으로 아주 좋은 기사 : The Absoultly minimum every developer must know about unicode