2012-05-10 34 views
3

我正在掉落unicode地獄。如何在python中打印0xfb

我的環境在UNIX,蟒蛇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) 

祝out.txt的結果是

readable 
fb is not \xfb 

readable 
fb is not 0xfb 

[解決方法]

#! /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一。 s2只是一系列字節,不能任意加到一個unicode對象上(而不是一系列代碼點)。

如果你本來打算「\ xfb的」來表示U+FBLATIN SMALL LETTER U WITH CIRCUMFLEX,這本來是更好地分配它像這個:

s2 = u"\u00fb" 

但是你說你只是想打印出\ XHH代碼控制字符。如果你只是想讓它成爲人類可以理解的東西,但是仍然可以看出特殊字符在字符串中,那麼repr就足夠了。首先,沒有s是一個unicode對象,因爲您將字符串視爲一系列字節,而不是一系列代碼點。

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

print repr(s) 

最後,如果你不想在外面額外的報價是repr補充說,對於好的漂亮的印刷或什麼的,有沒有這樣做,在Python(據我所知)一個簡單的內建的方法。我用這樣的事情之前:

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('\\', '\\\\')) 

你可以很容易地調整了controlchars_re正則表達式來定義有關轉義你關心的字符。

+0

謝謝,你的代碼幾乎是答案,如果s2是可讀的,我只想顯示它爲普通字符串,如果它不能,顯示爲十六進制。實際上,'''print''''僅用於調試。我只是想轉換爲文本文件。 –

+0

然後你可能只想使用'repr(s)'。這將打印字符串的方式,你可以將它粘貼回Python並獲得相同的值,所以任何特殊字符都會得到反斜槓。 –

+0

如果我將escape_special_characters()生成的字符串寫入文件。我可以將它們從文件讀回到原始二進制數據嗎? –