5

「ok1、ok2、ok3」という名前のgeditを使用して、同じコンテンツ「你」(you英語)を含む3つのファイルを3つの異なる形式(gbk\utf-8\ucs-2)で編集します。

>>> 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' ですが、次の出力で混乱しました

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

gbk ではなく、utf-8 ではなく、ucs-2 (またはユニコードと言う) にのみエンディアンの問題があるのはなぜですか?

4

2 に答える 2

5

UTF-8GBKは、データを一連のバイトで格納します。これらのエンコーディングでは、どのバイト値がその後に続くかが厳密に定義されています。このバイト順序は、コーディング、送信、またはデコードで使用されるアーキテクチャによって変わりません。

一方、UCS-2または新しいUTF-16は、データを 2 バイトのシーケンスで格納します。これらの 2 バイト トークン内の個々のバイトの順序はエンディアンであり、基盤となるマシン アーキテクチャによって異なります。システムは、 UCS-2でエンコードされたデータと通信する前に、トークンのエンディアンを識別する方法について合意している必要があります。

あなたの場合、Unicode ポイント U+4F60 はUCS-2で単一の 2 バイト token としてコード化されています0x4F60。お使いのマシンはメモリ アラインメントで最上位バイトの前に最下位バイトを配置するため、シーケンス('0x60', '0x4F')はファイルに配置されています。したがって、ファイルを読み取ると、この順序でバイトが生成されます。

Python は、2 バイトのトークンを形成する前に正しい順序でバイトを読み取るため、このデータを正しくデコードできます。

>>> '`O\n\x00'.decode('utf-16')
u'\u4f60\n'
于 2012-09-08T07:17:04.263 に答える
5

エンディアンはマルチバイトの単語にのみ適用されますが、UTF-8 は 8 ビットの単位を使用して情報をエンコードします (名前の 8 はこれを表します)。そこには注文の混乱の問題は決してありません。

情報をエンコードするためにこれらのユニットが複数必要になる場合もありますが、それらは別個のものと見なされます。たとえば、文字Aは 1 バイトです。0x41より多くのバイトで文字をエンコードする必要がある場合は、先行インジケータ バイトを使用し、その後に追加の継続バイトを使用して、その文字に必要なすべての情報をキャプチャします。論理的には、これらは別個の単位です。

GBK も同様のスキームを使用します。文字は 1 バイトの単位を使用し、UTF-8 と同様に、一部の文字には 2 番目のバイトを使用できます。

一方、UCS-2 (およびその後継の UTF-16) は 2 バイト形式です。情報を 16 ビット単位でエンコードし、その 16 ビットは常に一緒になります。その単位の 2 バイトは論理的に一緒に属しており、最新のアーキテクチャではこれらを 1 つの単位として扱い、格納する順序を決定しています。そこでエンディアンの出番です。ユニット内の 2 バイトの順序はアーキテクチャに依存します。あなたのアーキテクチャでは、バイトはリトルエンディアンを使用して順序付けられます。つまり、「小さい」バイトが最初になります。これが、バイトがファイル内0x4Fのバイトの前に来る理由です。0x60

Python は、ビッグ エンディアンまたはリトル エンディアンの 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'

後者の例では、バイトが反転され、ビッグエンディアンとしてデコードされています。

于 2012-09-08T07:21:30.283 に答える