10

データをファイルに保存して書き込む Python プログラムがあります。データは未加工のバイナリ データであり、内部的に として保存されstrます。utf-8コーデックで書き込んでいます。しかし、私UnicodeDecodeError: 'charmap' codec can't decode byte 0x8d in position 25: character maps to <undefined>cp1252.pyファイルに入ります。

これは、Python がデフォルトのコード ページを使用してデータを解釈しようとしているように見えます。ただし、デフォルトのコード ページありません。そのためstr、 ではなくを使用していunicodeます。

私の質問は次のとおりです。

  • Pythonで生のバイナリデータをメモリ内で表現するにはどうすればよいですか?
  • コーデックを介して生のバイナリ データを書き出す場合、それをエンコード/エンコード解除するにはどうすればよいですか?
4

3 に答える 3

22

注:これはPython2.x用に作成されました。3.xに該当するかどうかわからない。

strメモリ内の生のバイナリデータの使用は正しいです。
[Python 2.6以降を使用している場合bytesは、2.6以降では単なるエイリアスであるstrが意図をより適切に表現するものを使用することをお勧めします。いつかコードをPython3に移植する場合に役立ちます。]

他の人が指摘しているように、コーデックを介してバイナリデータを書き込むのは奇妙です。書き込みコーデックはUnicodeを受け取り、ファイルにバイトを出力します。あなたはそれを逆行しようとしているので、あなたの意図についての私たちの混乱...

[そして、エラーの診断は正しいように見えます。コーデックはユニコードを想定しているため、Pythonはシステムのデフォルトのエンコーディングであるチョークを使用してstrをユニコードにデコードしています。]

出力ファイルに何を見たいですか?

  • ファイルにバイナリデータをそのまま含める必要がある場合

    次に、コーデックを介して送信してはなりません。ファイルに直接書き込む必要があります。コーデックはすべてをエンコードし、Unicodeの有効なエンコード(この場合は有効なUTF-8)のみを出力できます。任意のバイトシーケンスを出力させるために与えることができる入力はありません!

    • UTF-8と生のバイナリデータを混在させる必要がある場合は、ファイルを直接開いて、書き込みを...と混合する必要ありsome_data ますsome_text.encode('utf8')

    ただし、UTF-8を生の任意のデータと混合することは、そのようなファイルの処理が非常に不便であるため、非常に悪い設計であることに注意してください。Unicodeを理解するツールは、バイナリデータを詰まらせ、ファイルを表示(変更は言うまでもなく)する便利な方法さえも残します。

  • Unicodeで任意のバイトをわかりやすく表現したい場合

    data.encode('base64')コーデックに渡します。Base64は、クリーンなASCII(文字、数字、および小さな句読点)のみを生成するため、何にでも明確に埋め込むことができ、バイナリデータとして人々に明確に見え、適度にコンパクトです(33%をわずかに超えるオーバーヘッド)。

    PSあなたはそれdata.encode('base64')が奇妙であることに気付くかもしれません。

    • .encode()ユニコードを取ることになっていますが、私はそれに文字列を与えていますか?!Pythonには、「base64」や「zlib」など、str->strを変換するいくつかの疑似コーデックがあります。

    • .encode()常にstrを返しますが、Unicodeを期待してコーデックにフィードしますか?!この場合、クリーンなASCIIのみが含まれるため、問題ありません。data.encode('base64').encode('utf8')気分が良くなる場合は、明示的に書く ことができます。

  • 任意のバイトからUnicodeへの1:1マッピングが必要な場合

    data.decode('latin1')コーデックに 渡します。latin1バイト0〜255をUnicode文字0〜255にマップします。これは、ちょっとエレガントです。

    もちろん、コーデックは文字をエンコードします-128-255はUTF-8で2または3バイトとしてエンコードされます(驚くべきことに、平均オーバーヘッドは50%で、base64よりも多くなります!)。これは、1:1のマッピングを持つという「エレガンス」を完全に殺します。

    また、Unicode文字0〜255には、厄介な非表示/制御文字(改行、フォームフィード、ソフトハイフンなど)が含まれているため、バイナリデータをテキストエディタで表示するのが面倒です。

    これらの欠点を考慮して、なぜ必要なのかを正確に理解していない限り、latin1はお勧めしません。
    私はそれを頭に浮かぶ他の「自然な」エンコーディングとして言及しているだけです。

于 2010-04-11T17:23:27.547 に答える
0

最初の質問: Python では、通常の文字列(つまり、Unicode 文字列ではない) はバイナリ データです。Unicode 文字列とバイナリ データを書きたい場合は、Unicode 文字列をバイナリ データに変換し、それらをまとめます。

# encode the unicode string as a string
bytes = unicodeString.encode('utf-8')
# add it to the other string
raw_data += bytes
# write it all to a file
yourFile.write(raw_data)

2 番目の質問:write()生データです。次に、それを読むときは、次のようにします。

import codecs
yourFile = codecs.open( "yourFileName", "r", "utf-8" )
# and now just use yourFile.read() to read it
于 2010-04-09T22:32:53.133 に答える
0

strコーデックをに変換する場合を除いて、通常は でコーデックを使用しないでくださいunicodelatin-1ユニコードに「生の」データが必要だと思う場合は、おそらくコーデックの使用を検討する必要があります。

于 2010-04-09T22:02:22.017 に答える