2016-07-29 17 views
4

ここでは、オープン、読み取り、出力の方法を示します。このファイルは、Unicode文字用のUTF-8エンコードファイルです。私は最初の10 UTF-8文字を印刷したいが、下のコードスニペットからの出力は奇妙な認識できない文字を印刷する。誰かが正しく印刷する方法を知っているのだろうか?ありがとう。Python 2.7のUTF-8文字を印刷

with open(name, 'r') as content_file: 
     content = content_file.read() 
     for i in range(10): 
      print content[i] 

10奇妙な文字は、それぞれ出力するに

に関して、 林

+1

™あなたのコンソールまたはTTYが同様の文字をサポートしている必要があり –

+1

テキストファイルの内容を共有する - あなたは、端末の設定を変更する必要があるかもしれません。 – cdarke

+0

@cdarke、ありがとうございました。私のコンソールは 'コンテンツを正しく印刷できました。これはUTF-8文字をサポートしているはずです。この問題は、 'content [i]'を印刷する場合にのみ発生します。あなたが思考を持っているなら、それは素晴らしいでしょう。 –

答えて

10

Unicodeのコードポイント(文字)はUTF-8、いくつかのコードポイントがあるとしてエンコードされています1バイトに変換されますが、多くのコードポイントは1バイト以上になります。標準の7ビットASCII範囲の文字は1バイトとしてエンコードされますが、よりエキゾチックな文字は一般にエンコードするためにより多くのバイトを必要とします。

これらのマルチバイトUTF-8シーケンスを1バイトに分割しているので、これらの奇妙な文字を取得しています。いつもそれらのバイトは通常の印字可能文字に対応しますが、しばしば印字されることはありません。

ここでは、UTF-8でそれぞれ2バイト、2バイト、3バイトにエンコードされた©、®、および™文字を使用した短いデモを紹介します。私の端末はUTF-8を使うように設定されています。

utfbytes = "\xc2\xa9 \xc2\xae \xe2\x84\xa2" 
print utfbytes, len(utfbytes) 
for b in utfbytes: 
    print b, repr(b) 

uni = utfbytes.decode('utf-8') 
print uni, len(uni) 

出力

© ® ™ 9                                   
� '\xc2'                                  
� '\xa9'                                  
    ' ' 
� '\xc2' 
� '\xae' 
    ' ' 
� '\xe2' 
� '\x84' 
� '\xa2' 
© ® ™ 5 

スタックオーバーフロー共同創設者、ジョエル・スポルスキは、ユニコードに良い記事を書いています:The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)

あなたはまた、中Unicode HOWTO記事を見てみる必要がありますPythonのドキュメント、Ned BatchelderのPragmatic Unicodeの記事「Unipain」


ここでは、UTF-8でエンコードされたバイト文字列から個々の文字を抽出する簡単な例を示します。コメントで言及したように、これを正しく行うには、各文字がエンコードされているバイト数を知る必要があります。私たちはUTFの文字のバイト幅がわからない場合

utfbytes = b"\xc2\xa9 \xc2\xae \xe2\x84\xa2" 
widths = (2, 1, 2, 1, 3) 
start = 0 
for w in widths: 
    s = utfbytes[start:start+w] 
    print("%d %d [%s]" % (start, w, s.decode())) 
    start += w 

utfbytes = "\xc2\xa9 \xc2\xae \xe2\x84\xa2" 
widths = (2, 1, 2, 1, 3) 
start = 0 
for w in widths: 
    print "%d %d [%s]" % (start, w, utfbytes[start:start+w]) 
    start += w 

出力

0 2 [©] 
2 1 [ ] 
3 2 [®] 
5 1 [ ] 
6 3 [™] 

FWIWは、ここではそのコードのPythonの3バージョンです-8文字列を入力すると、もう少し作業が必要になります。各UTF-8シーケンスは、the Wikipedia article on UTF-8で説明されているように、最初のバイトのシーケンスの幅をエンコードします。

次のPython 2のデモでは、幅情報をどのように抽出できるかを示しています。前の2つのスニペットと同じ出力を生成します。

# UTF-8 code widths 
#width starting byte 
#1 0xxxxxxx 
#2 110xxxxx 
#3 1110xxxx 
#4 11110xxx 
#C 10xxxxxx 

def get_width(b): 
    if b <= '\x7f': 
     return 1 
    elif '\x80' <= b <= '\xbf': 
     #Continuation byte 
     raise ValueError('Bad alignment: %r is a continuation byte' % b) 
    elif '\xc0' <= b <= '\xdf': 
     return 2 
    elif '\xe0' <= b <= '\xef': 
     return 3 
    elif '\xf0' <= b <= '\xf7': 
     return 4 
    else: 
     raise ValueError('%r is not a single byte' % b) 


utfbytes = b"\xc2\xa9 \xc2\xae \xe2\x84\xa2" 
start = 0 
while start < len(utfbytes): 
    b = utfbytes[start] 
    w = get_width(b) 
    s = utfbytes[start:start+w] 
    print "%d %d [%s]" % (start, w, s) 
    start += w 

一般的には、は、この種のものを行うには必要はありません。ただ提供する復号方法を使用します。好奇心のために


、ここget_widthのPythonの3バージョン、およびUTF-8手動バイト文字列をデコードする機能です。

def get_width(b): 
    if b <= 0x7f: 
     return 1 
    elif 0x80 <= b <= 0xbf: 
     #Continuation byte 
     raise ValueError('Bad alignment: %r is a continuation byte' % b) 
    elif 0xc0 <= b <= 0xdf: 
     return 2 
    elif 0xe0 <= b <= 0xef: 
     return 3 
    elif 0xf0 <= b <= 0xf7: 
     return 4 
    else: 
     raise ValueError('%r is not a single byte' % b) 

def decode_utf8(utfbytes): 
    start = 0 
    uni = [] 
    while start < len(utfbytes): 
     b = utfbytes[start] 
     w = get_width(b) 
     if w == 1: 
      n = b 
     else: 
      n = b & (0x7f >> w) 
      for b in utfbytes[start+1:start+w]: 
       if not 0x80 <= b <= 0xbf: 
        raise ValueError('Not a continuation byte: %r' % b) 
       n <<= 6 
       n |= b & 0x3f 
     uni.append(chr(n)) 
     start += w 
    return ''.join(uni) 


utfbytes = b'\xc2\xa9 \xc2\xae \xe2\x84\xa2' 
print(utfbytes.decode('utf8')) 
print(decode_utf8(utfbytes)) 

出力

®©®©

+0

PM 2Ringに感謝、あなたの返事を投票してください。あなたの方法はかなりうまくいくと試しました。元の文字列にUnicode文字(たとえば中国語/日本語文字)があり、UTF-8でエンコードされた同じ文字列に英字がある場合、最初の文字は漢字、2番目の文字はASCII文字'a'(どちらもUTF-8でエンコードされています)。 'utfbytes.decode( 'utf-8')'を呼び出すと、2番目の文字を 'utfbytes [1]'で参照すると 'a'を正しく認識できるでしょうか? –

+0

(続き)マルチバイト文字やシングルバイト文字について言及して以来、私はこの混乱を抱えていました。元のUTF-8でエンコードされた文字列を混在させた場合、どのように動作するのだろうかと思います。ありがとう。 –

+0

ところで、私は 'utfbytes [1]'、 'a'を正しく出力できたと思っていました。私の理解が正しいことを確認するだけです。ありがとう。 –

2

Unicode文字列ファイルまたはテキストを選択する必要がコンソールに、次のようになりますエンコーディング。 Pythonでは、デフォルトのテキストエンコーディングはASCIIですが、あなたは、このようなUTF-8のように、異なるエンコーディングを使用する必要があり、他の文字をサポートするために:

s = unicode(your_object).encode('utf8') 
print s 
+0

ありがとうございました。あなたのコード中の 'your_object'を 'content'に置き換えることはできますか? –

関連する問題