2012-09-08 2 views
5

나는 "ok", "ok2", "ok3"라는 gedit을 가진 gbk \ utf-8 \ ucs-2와 동일한 내용 "你"(영어로 you) ". 하지에 (또는 유니 코드를 말한다)유니 코드 엔디안이 나를 어리둥절하게했다

>>> f1 = open('ok1', 'rb').read() 
>>> f2 = open('ok2', 'rb').read() 
>>> f3 = open('ok3', 'rb').read() 
>>> f1 
'\xc4\xe3\n' 
>>> f2 
'\xe4\xbd\xa0\n' 
>>> f3 
'`O\n\x00' 
>>> hex(ord("`")) 
'0x60' 
>>> hex(ord("O")) 
'0x4f' 

사실 F3는 '\ X60 \ x4f' 하지만 다음과 같은 출력은 나에게 단 UCS-2 엔디안 문제가 왜

>>> '\xe4\xbd\xa0'.decode("utf-8") 
u'\u4f60' 
>>> '\xc4\xe3'.decode("gbk") 
u'\u4f60' 
>>> 

혼란 utf-8, gbk가 아닌가요?

답변

5

UTF-8GBK은 바이트 순서로 데이터를 저장합니다. 이러한 인코딩에서 어떤 바이트 값이 올지를 강력하게 정의합니다. 이 바이트 순서는 코딩, 전송 또는 디코딩에 사용 된 아키텍처와 함께 변경되지 않습니다. 한편

, UCS -2- 또는 2- 바이트 시퀀스에서 새로운 UTF-16 스토어 데이터. 이 2 바이트 토큰 내의 개별 바이트 순서는 엔디안 (endianness)이며 기본 시스템 아키텍처에 따라 다릅니다. 시스템은 UCS-2으로 인코딩 된 데이터와 통신하기 전에 토큰의 엔디안을 식별하는 방법에 대한 합의가 있어야합니다.

유니 코드 포인트 U + 4F60은 UCS-2의 코드로 단일 2 바이트 토큰 0x4F60으로 코딩됩니다. 여러분의 머신은 메모리 정렬에서 가장 중요한 바이트 앞에 최하위 바이트를 놓기 때문에, 시퀀스 ('0x60', '0x4F')이 파일에 저장됩니다. 따라서, 파일 읽기는이 순서로 바이트를 산출합니다.

파이썬은 여전히 ​​2 바이트 토큰 형성하기 전에 올바른 순서 바이트를 판독하기 때문에 올바르게 데이터를 디코딩 할 수

>>> '`O\n\x00'.decode('utf-16') 
u'\u4f60\n' 
+0

컴퓨터가 메모리 정렬에서 가장 중요한 바이트 앞에 놓기 때문에 시퀀스 ('0x60', '0x4F')가 파일에 저장됩니다. 따라서 파일 읽기는이 순서대로 바이트를 생성합니다. 내 컴퓨터에서 f1은 '\ xe3 \ xc4 \ n'이 아니므로 ?? f2는 f2 '가 아닙니다. \ xbd \ xe4 \ xa0 \ n' –

+0

@Dd Pp : utf-8 파일을 쓸 때 gedit은 바이트 *를 하나씩 저장하기 때문에 *. 그러나 ucs-2 코드 파일을 작성할 때 gedit은 바이트를 2 x 2로 지정합니다. 바이트 내의 순서는 후자의 경우에만 엔디안에 따라 다릅니다. –

3

엔디안만을 멀티 바이트 워드 적용을하지만, UTF-8 8 비트의 단위를 사용하여 정보를 인코딩합니다 (이름의 8이 의미하는 것입니다). 거기에 주문의 혼란에 대한 질문이 결코 없습니다.

때로는 정보를 인코딩하기 위해 두 개 이상의 단위가 필요할 수도 있지만 별개로 간주됩니다. 문자 A은 1 바이트, 예를 들어 0x41입니다. 더 많은 바이트가있는 문자를 인코딩해야하는 경우 선행 표시기 바이트를 사용하고 추가 연속 바이트를 사용하여 해당 문자에 필요한 모든 정보를 캡처합니다. 논리적으로, 이들은 별개의 단위입니다.

GBK도 비슷한 체계를 사용합니다. 문자는 1 바이트 단위를 사용하며 UTF-8과 마찬가지로 일부 문자에는 두 번째 바이트를 사용할 수 있습니다.

반면에 UCS-2 (및 그 후계자, UTF-16)는 2 바이트 형식입니다. 정보를 16 비트 단위로 인코딩하며, 16 비트는 항상 함께 사용됩니다. 그 단위의 2 바이트는 논리적으로 함께 소속되어 있으며, 현대 건축물은 이것들을 하나의 단위로 취급하고 따라서 어떤 순서로 저장할지 결정했습니다. 그것이 엔디안이 들어오는 곳입니다. 한 유닛의 2 바이트 순서는 아키텍처에 따라 다릅니다. 아키텍처에서 바이트는 리틀 엔디안을 사용하여 정렬됩니다. 즉, '더 작은'바이트가 먼저 나옵니다. 이것이 0x4F 바이트가 파일의 0x60 바이트 앞에 오는 이유입니다.

파이썬은 큰 또는 작은 엔디안 UTF-16을 읽을 수 있습니다. 당신은 시작시에는 표시 문자 (바이트 순서 표시, 또는 BOM)이없는 경우 명시 적으로 엔디안을 선택할 수 있습니다 : 바이트가 반전 된 후자의 예에서

>>> '`O\n\x00'.decode('utf-16') 
u'\u4f60\n' 
>>> '`O\n\x00'.decode('utf-16-le') 
u'\u4f60\n' 
>>> 'O`\x00\n'.decode('utf-16-be') 
u'\u4f60\n' 

이, 그리고 빅 엔디안을 디코딩.