Python 转换文件的编码

  • 原创
  • Madman
  • /
  • /
  • 0
  • 1105 次阅读

Python编码转换.png

Synopsis: Linux 中有个 iconv 工具可以用来转换文件的编码,尝试用 Python 来实现部分功能,加深对字符编码的理解

建议先阅读:

1. Python 2.x

  • rb 的方式打开要读取的文件,接收二进制字节序列
  • 将字节序列转换成 unicode 类型对象
  • wb 的方式打开要写入的文件,将 unicode 对象按要转换的编码格式编码成字节序列写入目标文件
  • argparse 模块用来处理用户输入的命令行参数
# -*- coding: utf-8 -*-
import argparse
import logging
import sys

logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO)


def convert(from_code, to_code, input, output):
    """Convert File Encoding"""
    # 读取源文件
    try:
        f = open(input, 'rb')
    except IOError as e:  # 源文件或它的目录不存在时
        logging.error(e)
        sys.exit(1)
    content_bytes = f.read()  # 接收字节序列

    try:
        content_unicode = unicode(content_bytes, encoding=from_code)  # 按 from_code 解码成 Unicode code points
    except UnicodeDecodeError as e:
        logging.error('Encoding of input is wrong: %s' % e)
        sys.exit(1)
    f.close()

    # 写入目标文件
    try:
        f = open(output, 'wb')
    except IOError as e:  # 目标文件或它的目录不存在时
        logging.error(e)
        sys.exit(1)

    try:
        f.write(content_unicode.encode(to_code))  # 写入按 to_code 编码后的字节序列
    except UnicodeEncodeError as e:
        logging.error('Encoding of output is wrong: %s' % e)
        sys.exit(1)
    f.close()

    logging.info('Convert done.')


if __name__ == '__main__':
    # 解析命令行参数
    parser = argparse.ArgumentParser()
    parser.add_argument(
        '-f', '--from-code',
        metavar='NAME',
        required=True,
        help='encoding of original text'
    )
    parser.add_argument(
        '-t', '--to-code',
        metavar='NAME',
        required=True,
        help='encoding for output'
    )
    parser.add_argument(
        '-i', '--input',
        metavar='FILE',
        required=True,
        help='input file'
    )
    parser.add_argument(
        '-o', '--output',
        metavar='FILE',
        required=True,
        help='output file'
    )
    parser.add_argument(
        '-v', '--version',
        action='version',
        version='%(prog)s 1.0.0',
    )
    args = parser.parse_args()

    # 调用转换函数
    convert(args.from_code, args.to_code, args.input, args.output)

假设 gbk.txt 文件是以 GBK 编码的,由于 Linux 的默认编码是 UTF-8,所以查看 gbk.txt 的文件内容时会显示乱码。现在,需要将它转换成 UTF-8 编码:

[root@CentOS ~]# cat gbk.txt 
֢ˇ GBK τ¼þ

[root@CentOS ~]# python iconv-py2.py --help
usage: iconv-py2.py [-h] -f NAME -t NAME -i FILE -o FILE [-v]

optional arguments:
  -h, --help            show this help message and exit
  -f NAME, --from-code NAME
                        encoding of original text
  -t NAME, --to-code NAME
                        encoding for output
  -i FILE, --input FILE
                        input file
  -o FILE, --output FILE
                        output file
  -v, --version         show program's version number and exit

[root@CentOS ~]# python iconv-py2.py -f gbk -t utf-8 -i gbk.txt -o conv-gbk-to-utf8.txt
2019-10-27 23:23:41,935 - root - INFO - Convert done.

[root@CentOS ~]# cat conv-gbk-to-utf8.txt 
这是 GBK 文件

2. Python 3.x

  • r 的方式打开要读取的文件,Python 会自动将二进制字节序列转换成 Unicode(即 str 类型对象)
  • w 的方式打开要写入的文件,Python 会自动将 str 类型对象按要转换的编码格式编码成字节序列写入目标文件
  • argparse 模块用来处理用户输入的命令行参数
import argparse
import logging
import sys

logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO)


def convert(from_code, to_code, input, output):
    """Convert File Encoding"""
    # 读取源文件
    try:
        f = open(input, 'r', encoding=from_code)
    except FileNotFoundError as e:  # 源文件或它的目录不存在时
        logging.error(e)
        sys.exit(1)

    try:
        content = f.read()  # Python 自动根据 from_code 将接收到的字节序列解码成 str 对象
    except UnicodeDecodeError as e:
        logging.error('Encoding of input is wrong: %s' % e)
        sys.exit(1)
    f.close()

    # 写入目标文件
    try:
        f = open(output, 'w', encoding=to_code)
    except FileNotFoundError as e:  # 目标文件或它的目录不存在时
        logging.error(e)
        sys.exit(1)

    try:
        f.write(content)  # 首先,Python 自动根据 to_code 将 str 对象编码成字节序列,然后再写入目标文件中
    except UnicodeEncodeError as e:
        logging.error('Encoding of output is wrong: %s' % e)
        sys.exit(1)
    f.close()

    logging.info('Convert done.')


if __name__ == '__main__':
    # 解析命令行参数
    parser = argparse.ArgumentParser()
    parser.add_argument(
        '-f', '--from-code',
        metavar='NAME',
        required=True,
        help='encoding of original text'
    )
    parser.add_argument(
        '-t', '--to-code',
        metavar='NAME',
        required=True,
        help='encoding for output'
    )
    parser.add_argument(
        '-i', '--input',
        metavar='FILE',
        required=True,
        help='input file'
    )
    parser.add_argument(
        '-o', '--output',
        metavar='FILE',
        required=True,
        help='output file'
    )
    parser.add_argument(
        '-v', '--version',
        action='version',
        version='%(prog)s 1.0.0',
    )
    args = parser.parse_args()

    # 调用转换函数
    convert(args.from_code, args.to_code, args.input, args.output)

假设 gbk.txt 文件是以 GBK 编码的,由于 Linux 的默认编码是 UTF-8,所以查看 gbk.txt 的文件内容时会显示乱码。现在,需要将它转换成 UTF-8 编码:

[root@CentOS ~]# cat gbk.txt 
֢ˇ GBK τ¼þ

[root@CentOS ~]# python3 iconv-py3.py --help
usage: iconv-py3.py [-h] -f NAME -t NAME -i FILE -o FILE [-v]

optional arguments:
  -h, --help            show this help message and exit
  -f NAME, --from-code NAME
                        encoding of original text
  -t NAME, --to-code NAME
                        encoding for output
  -i FILE, --input FILE
                        input file
  -o FILE, --output FILE
                        output file
  -v, --version         show program's version number and exit

[root@CentOS ~]# python3 iconv-py3.py -f gbk -t utf-8 -i gbk.txt -o conv-gbk-to-utf8.txt
2019-10-27 23:28:53,248 - root - INFO - Convert done.

[root@CentOS ~]# cat conv-gbk-to-utf8.txt 
这是 GBK 文件

代码已上传到 Github,欢迎 star

分类: Python
标签: argparse str Unicode UTF-8
未经允许不得转载: LIFE & SHARE - 王颜公子 » Python 转换文件的编码

分享

作者

作者头像

Madman

如需 Linux / Python 相关问题付费解答,请按如下方式联系我

0 条评论

暂时还没有评论.