在Python 2.7中打印UTF-8字符

在Python 2.7中打印UTF-8字符,第1张

在Python 2.7中打印UTF-8字符

将Unipre代码点(字符)编码为UTF-8时,某些代码点将转换为单个字节,但是许多代码点会超过一个字节。标准7位ASCII范围内的字符将被编码为单个字节,但是更多的外来字符通常将需要更多的字节进行编码。

因此,您将获得那些奇怪的字符,因为您将这些多字节UTF-8序列分解为单个字节。有时这些字节将与正常的可打印字符相对应,但通常不会,因此您可以打印出来。

这是一个使用©,®和™字符的简短演示,它们在UTF-8中分别编码为2、2和3个字节。我的终端设置为使用UTF-8。

utfbytes = "xc2xa9 xc2xae xe2x84xa2"print utfbytes, len(utfbytes)for b in utfbytes:    print b, repr(b)uni = utfbytes.depre('utf-8')print uni, len(uni)

输出

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

Stack Overflow的联合创始人Joel
Spolsky在Unipre上写了一篇很好的文章:每个软件开发人员绝对绝对要完全了解Unipre和字符集(没有任何借口!)

您还应该看一下Python文档中的Unipre
HOWTO
文章,以及Ned
Batchelder的实用Unipre文章,也称为“
Unipain”。


这是从UTF-8编码的字节字符串中提取单个字符的简短示例。正如我在评论中提到的那样,要正确执行此 *** 作,您需要知道每个字符被编码为多少个字节。

utfbytes = "xc2xa9 xc2xae xe2x84xa2"widths = (2, 1, 2, 1, 3)start = 0for 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版本:

utfbytes = b"xc2xa9 xc2xae xe2x84xa2"widths = (2, 1, 2, 1, 3)start = 0for w in widths:    s = utfbytes[start:start+w]    print("%d %d [%s]" % (start, w, s.depre()))    start += w

如果我们不知道UTF-8字符串中字符的字节宽度,那么我们需要做更多的工作。每个UTF-8序列都会在第一个字节中编码该序列的宽度,如Wikipedia文章中有关UTF-8所述。

以下Python 2演示演示了如何提取该宽度信息。它产生与前两个片段相同的输出。

# UTF-8 pre widths#width starting byte#1 0xxxxxxx#2 110xxxxx#3 1110xxxx#4 11110xxx#C 10xxxxxxdef 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"xc2xa9 xc2xae xe2x84xa2"start = 0while start < len(utfbytes):    b = utfbytes[start]    w = get_width(b)    s = utfbytes[start:start+w]    print "%d %d [%s]" % (start, w, s)    start += w

一般来说,它应该 不会 有必要做这样的事情:只使用所提供的解码方法。


出于好奇,这里是的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 depre_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'xc2xa9 xc2xae xe2x84xa2'print(utfbytes.depre('utf8'))print(depre_utf8(utfbytes))

输出

©®™
©®™



欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/zaji/5674872.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-12-16
下一篇2022-12-16

发表评论

登录后才能评论

评论列表(0条)

    保存