python - 在 Python 2.7 中打印 UTF-8 字符

标签 python python-2.7 unicode utf-8

这是我打开、读取和输出的方式。该文件是用于 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]

这10个怪异的角色每一个都是这样的,

问候, 林

最佳答案

当 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)

输出

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

Stack Overflow 联合创始人 Joel Spolsky 写了一篇关于 Unicode 的好文章: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 编码字节字符串中提取单个字符的简短示例。正如我在评论中提到的,要正确执行此操作,您需要知道每个字符被编码为多少字节。

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 版本:

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

如果我们不知道 UTF-8 字符串中字符的字节宽度,那么我们需要做更多的工作。每个 UTF-8 序列在第一个字节中编码序列的宽度,如 the Wikipedia article on 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

通常,不需要做这种事情:只需使用提供的解码方法即可。


出于好奇,这里有一个 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))

输出

©®™
© ® ™

关于python - 在 Python 2.7 中打印 UTF-8 字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38651993/

相关文章:

elasticsearch - 如何在elasticsearch中搜索utf-8特殊字符?

python - 如何将DataFrame的行数限制为特定列中的第X个唯一值?

python - 使用 Jinja 流式传输 Flask 模板

Python I/O 读取和追加(写入)

sql-server - 在 SQL Server 中的韩语单词(任何 Unicode 单词)中查找韩语字母(任何 Unicode 字符)的索引

c# - 如何在 C# 中的文本框(实际上是任何字符串)中显示无限字符/符号?

python - 来自带有python的音频文件的1/3倍频程

python - 如何让 turtle 对象查看鼠标点击的位置

python - 如何将 dict 的值写入 openpyxl 中的空(新)列?

python - 编辑 number 的距离特定实现。 PYTHON