Lin*_* Ma 4 python unicode utf-8 python-2.7
这是我打开,阅读和输出的方式.该文件是用于unicode字符的UTF-8编码文件.我想打印前10个UTF-8字符,但下面代码片段的输出打印出10个奇怪的无法识别的字符.想知道是否有人有任何想法如何正确打印?谢谢.
with open(name, 'r') as content_file:
content = content_file.read()
for i in range(10):
print content[i]
Run Code Online (Sandbox Code Playgroud)
每个10个奇怪的角色都是这样的,
?
Run Code Online (Sandbox Code Playgroud)
问候,林
PM *_*ing 13
当Unicode代码点(字符)编码为UTF-8时,某些代码点将转换为单个字节,但许多代码点将变为多个字节.标准7位ASCII范围中的字符将被编码为单个字节,但更奇特的字符通常需要更多字节来编码.
因此,您正在获取那些奇怪的字符,因为您将这些多字节UTF-8序列分解为单个字节.有时这些字节将对应于正常的可打印字符,但通常它们不会因此而是打印.
这是一个使用©,®和™字符的简短演示,它们分别以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)
Run Code Online (Sandbox Code Playgroud)
产量
© ® ™ 9
? '\xc2'
? '\xa9'
' '
? '\xc2'
? '\xae'
' '
? '\xe2'
? '\x84'
? '\xa2'
© ® ™ 5
Run Code Online (Sandbox Code Playgroud)
Stack Overflow联合创始人Joel Spolsky撰写了一篇关于Unicode的好文章:绝对最低限度每个软件开发人员绝对必须知道Unicode和字符集(没有借口!)
您还应该查看Python文档中的Unicode HOWTO文章和Ned Batchelder的Pragmatic Unicode文章,即"Unipain".
这是从UTF-8编码的字节串中提取单个字符的简短示例.正如我在评论中提到的,要正确执行此操作,您需要知道每个字符编码的字节数.
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
Run Code Online (Sandbox Code Playgroud)
产量
0 2 [©]
2 1 [ ]
3 2 [®]
5 1 [ ]
6 3 [™]
Run Code Online (Sandbox Code Playgroud)
FWIW,这是该代码的Python 3版本:
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
Run Code Online (Sandbox Code Playgroud)
如果我们不知道UTF-8字符串中字符的字节宽度,那么我们需要做更多的工作.每个UTF-8序列编码第一个字节中序列的宽度,如维基百科关于UTF-8的文章中所述.
以下Python 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
Run Code Online (Sandbox Code Playgroud)
通常,没有必要做这样的事情:只使用提供的解码方法.
对于好奇,这是一个Python 3版本get_width,以及一个手动解码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))
Run Code Online (Sandbox Code Playgroud)
产量
©®™
©®™
要将Unicode字符串输出到文件或控制台,您需要选择文本编码.在Python中,默认文本编码是ASCII,但是为了支持其他字符,您需要使用不同的编码,例如UTF-8:
s = unicode(your_object).encode('utf8')
print s
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
18121 次 |
| 最近记录: |