Python字符串编码相关介绍

Sep 16,2019   4004 words   15 min

Tags: Python

用过Python2.x的小伙伴应该都知道,它默认对中文是不支持的,需要手动设置一下(# coding=utf-8)。这个问题在Python3.x中已经得到了解决,Python3.x中将UTF-8作为了默认编码。但目前仍有大量使用Python2.x的情况,比如我。所以如何正确处理中文是一个十分重要的问题,而这本质上是Python对字符串编码及其转换的问题。

1.不同编码

常见的编码有ACSII、Unicode、UTF-8、GB2312、GBK等。下面简单介绍:

  • ASCII:全称是American Standard Code for Information Interchange,美国信息交换标准代码,最简单的西文编码方案。共有128个字符(数字、大小写字母以及部分特殊符号等),主要用于显示现代英语和其它西欧语言。占1字节。

  • Unicode:统一码、万国码,是计算机科学领域里的一项业界标准,能够使计算机实现跨语言、跨平台的文本转换及处理。

  • UTF-8:8-bit Unicode Transformation Format,是一种针对Unicode的可变长度字符编码。UTF-8用1到4个字节编码Unicode字符。英文占1个字节、欧洲语系占2个、东亚占3个,其它及特殊字符占4个。中文3个字节。用在网页上可以统一页面显示中文简体繁体及其它语言(如英文,日文,韩文)。

  • GB2312:《信息交换用汉字编码字符集》是由中国国家标准总局1980年发布,1981年5月1日开始实施的一套国家标准,标准号是GB2312—1980。基本集共收入汉字6763个和非汉字图形字符682个。占2个字节。

  • GBK:《汉字内码扩展规范》,GBK即“国标”、“扩展”汉语拼音的第一个字母,英文名称:Chinese Internal Code Specification。GBK向下与GB2312编码兼容,是它的升级版,共收录了21003个汉字,支持国际标准ISO/IEC10646-1和国家标准GB13000-1中的全部中日韩汉字,并包含了BIG5编码中的所有汉字。中文占2个字节。

通过上面的介绍可以看到,Unicode是一种通用型编码,其能表示的语言最多,但同时带来的问题是其存储量也较大。而UTF-8可以看作是一种压缩版的Unicode,采用可变长编码降低了数据量。所以一般做法是处理用Unicode,储存用UTF-8,如果只有中文、英文等,则可以用GBK或GB2312进一步减小存储空间。

2.字符串编码判断

在介绍了这些编码方式后,如何判断读取的字符串是什么编码呢?需要用到一个叫做chardet的包,包中有detect()函数,只需传入待判断的字符串即可得到结果。简单使用示例如下:

# coding=utf-8
import chardet

if __name__ == '__main__':
    str1 = "你好啊!"
    str2 = "Hello"
    print chardet.detect(str1)
    print chardet.detect(str2)

运行结果如下: 利用这个函数即可以方便地判断字符串编码,但需要注意的一个问题是该函数不能判断Unicode编码类型的字符串。对于Unicode类型的字符串可以通过类型判断。Python中Unicode字符串是Unicode类,而其它编码字符串是str。可以自己写一个判断函数如下:

# coding=utf-8


def isUnicode(str):
    if type(str) is unicode:
        return True
    else:
        return False


if __name__ == '__main__':
    # python中unicode编码在字符串前面加u即可
    str1 = u"你好啊!"
    print isUnicode(str1)

此外可以用以下代码来设置系统默认编码:

    # 获取系统默认编码
    print 'before default encoding', sys.getdefaultencoding()
    
    # 设置系统默认编码
    reload(sys)
    sys.setdefaultencoding('utf8')
    
    # 再次获取系统默认编码
    print 'after default encoding', sys.getdefaultencoding()

3.编码转换

在Python中,读取的包含中文的路径、控制台输入的带有中文的字符串等是UTF-8编码,而有时读取的中文内容是GBK或GB2312编码这样就会导致乱码。Python中可以利用decode()encode()函数进行转码。函数decode()可以实现其它编码到Unicode的转换,函数encode()实现Unicode到其它编码方式的转换。

Python中编码转换的原则是,不管是什么编码都可以直接和Unicode互转,而要想实现如UTF8转GBK,则必须要以Unicode为媒介,先将UTF8转成Unicode编码,再将Unicode编码转成GBK编码。下面以UTF和Unicode互转为例进行介绍。

# coding=utf-8
import chardet


def isUnicode(str):
    if type(str) is unicode:
        return True
    else:
        return False


if __name__ == '__main__':
    # unicode转utf-8
    str1 = u"你好啊!"
    str2 = str1.encode('utf8')
    print chardet.detect(str2)

    # utf-8转unicode
    str3 = "Hello!大家好"
    str4 = unicode(str3, 'utf8')
    print isUnicode(str4)

4.编码转换实例

这里以一个实际需求来讲解,遍历获取文件名称(中英文混合),将名称中中文的顿号替换成-,并将结果输出到txt文件中。代码如下。

# coding=utf-8
import os


def isUnicode(str):
    if type(str) is unicode:
        return True
    else:
        return False


def findAllFiles(root_dir, filter):
    # 将输入字符串同一转成Unicode编码
    uni_root_dir = root_dir.decode('gbk')
    uni_filter = filter.decode('gbk')

    separator = os.path.sep
    paths = []
    names = []
    files = []
    for parent, dirname, filenames in os.walk(uni_root_dir):
        for filename in filenames:
            if filename.endswith(uni_filter):
                paths.append((parent + separator))
                names.append(filename)
    for i in range(paths.__len__()):
        files.append(paths[i] + names[i])
    paths.sort()
    names.sort()
    files.sort()
    return paths, names, files


def replaceDunHao(string, replace):
    if string.__contains__(u'、'):
        dun = string.find(u'、')
        # 对于unicode字符串,直接+1即可
        string = string[:dun] + replace + string[dun + 1:]
        return string


def replaceSharp(string, replace):
    if string.__contains__(u'#'):
        sharp = string.find(u'#')
        string = string[:sharp] + replace + string[sharp + 1:]
        return string


if __name__ == '__main__':
    _, _, files = findAllFiles(".", ".md")
    modi_files = []
    for item in files:
        print item
        # 替换中文顿号
        while item.__contains__(u'、'):
            item = replaceDunHao(item, u'-')
        # 替换井号
        while item.__contains__(u'#'):
            item = replaceSharp(item, u'-')
        modi_files.append(item)

    f = open("out.txt", 'w')
    for item in modi_files:
        f.write(item.encode('utf8') + "\n")
    f.close()

控制台输出如下: 输出的文本文件如下: 可以看到实现了我们一开始提出的需求。不仅如此,利用GBK编码还可以对日文等文字进行读写,如下。

另外插一句题外话,Python中有很方便的方法可以去除List中重复的元素。具体就是先把List转换成Set,然后再将Set转换成List即可。比如下面的代码。

num_list = [1,1,5,3,3,2,7,5]
num_list_new = list(set(num_list))
num_list_new.sort()

上面的代码就是对List中的重复元素进行了删除,同时按照默认从小到大的顺序排序。注意Sort()函数直接对自身操作,是没有返回值的。

5.参考资料

  • [1]https://www.cnblogs.com/yunguoxiaoqiao/p/7588725.html
  • [2]https://www.cnblogs.com/schut/p/8407258.html
  • [3]https://www.cnblogs.com/zihe/p/6993891.html

本文作者原创,未经许可不得转载,谢谢配合

返回顶部