2012-05-10 23 views
3

私はユニコードの地獄に落ちています。pythonで0xfbを印刷するには

UNIX上で

私の環境で、Pythonの2.7.3

LC_CTYPE=zh_TW.UTF-8 
LANG=en_US.UTF-8 

私はここにコード

#! /usr/bin/env python 
# encoding:utf-8 
import sys 

s=u"readable\n" # previous result keep in unicode string 
s2="fb is not \xfb" # data read from binary file 
s += s2 

print s # method 1 
print s.encode('utf-8') # method 2 
print s.encode('utf-8','ignore') # method 3 
print s.decode('iso8859-1') # method 4 

# method 1-4 display following error message 
#UnicodeDecodeError: 'ascii' codec can't decode byte 0xfb 
# in position 0: ordinal not in range(128) 

f = open('out.txt','wb') 
f.write(s) 

簡素化され、人間が読める形式で進エンコードされたデータをダンプしようとしている私はしたいです0xfbを出力します。

ここで詳しく説明します。キーは 's + = s2'です。 ここで、sは前のデコードされた文字列を保持します。s2はsに追加すべき次の文字列です。

次のように変更した場合は、書き込みファイルで発生します。

s=u"readable\n" 
s2="fb is not \xfb" 
s += s2.decode('cp437') 
print s 
f=open('out.txt','wb') 
f.write(s) 
# UnicodeEncodeError: 'ascii' codec can't encode character 
# u'\u221a' in position 1: ordinal not in range(128) 

私は強くあなたのコードが実際にerroringていると思われる

readable 
fb is not \xfb 

または

readable 
fb is not 0xfb 

あるout.txtをした結果に[ソリューション]

#! /usr/bin/env python 
# encoding:utf-8 
import sys 
import binascii 

def fmtstr(s): 
    r = '' 
    for c in s: 
     if ord(c) > 128: 
      r = ''.join([r, "\\x"+binascii.hexlify(c)]) 
     else: 
      r = ''.join([r, c]) 
    return r 

s=u"readable" 
s2="fb is not \xfb" 
s += fmtstr(s2) 
print s 
f=open('out.txt','wb') 
f.write(s) 
+0

'encode'を使うと*同じ*エラーメッセージが表示されますか? 'utf8'コーデックがデコードできません... *? – kojiro

+3

\ xfbはUTF-8ではないので、それは何ですか? –

+0

'\ xfb'はバイナリファイルから読み込まれたバイナリデータです。私は人間が読めるように '0xfbまたは\ xfb'として表示したい。 –

答えて

3

を望みます前の行にある:s += s2 1。 s2は単なる一連のバイトであり、ユニコードオブジェクト(これは一連のコードポイント)に任意に付けることはできません。あなたがU+FBLATIN SMALL LETTER U WITH CIRCUMFLEXを表現するために「\ XFB」を意図していた場合

、代わりに、このようにそれを割り当てるにはもっと良かったはず:

s2 = u"\u00fb" 

しかし、あなたはちょうど\ xHHをプリントアウトしたいと言いました制御文字のコード。文字が文字列であることが明らかになっている人間が理解できるようにするには、reprで十分でしょう。まず、sをユニコードオブジェクトにしないでください。ここでは、文字列を一連のコードポイントではなく、一連のバイトとして扱うためです。あなたはreprが素敵なきれいな印刷または何のために、追加することを外に余分な引用符を使用しない場合は

s = s.encode('utf-8') 
s += s2 

print repr(s) 

は最後に、(私の知っていること)、Pythonでそれを行うためのシンプルな組み込みの方法はありません。あなたはかなり簡単にあなたがエスケープを気にしている文字を定義するためにcontrolchars_re正規表現を微調整することができ

import re 
controlchars_re = re.compile(r'[\x00-\x31\x7f-\xff]') 

def _show_control_chars(match): 
    txt = repr(match.group(0)) 
    return txt[1:-1] 

def escape_special_characters(s): 
    return controlchars_re.sub(_show_control_chars, s.replace('\\', '\\\\')) 

:私は前にこのようなものを使用しました。

+0

ありがとうございます、あなたのコードはほとんど答えです.S2が読み込み可能であれば、私はちょうど通常の文字列として表示することができます。実際、 '' 'print' ''はデバッグ用です。テキストファイルに変換したいだけです。 –

+0

あなたは単に 'repr(s)'を使いたいかもしれません。これは文字列をPythonに貼り付けて同じ値を返すことができるように文字列を出力するので、特殊文字はすべてバックスラッシュになります。 –

+0

escape_special_characters()が文字列をファイルに書き込んだとします。ファイルから元のバイナリデータに戻すことができますか? –