文件编码

chardet

python chardet.detect 方法可以对输入的数据进行编码检测, 如下代码所示:

filename = "mycsv.csv"# sys.argv[0]
import chardet
with open(filename, "rb") as fp:
    print(chardet.detect(fp.read(1000)))

检测结果 UTF-16, 可信度 100%
{'encoding': 'UTF-16', 'confidence': 1.0, 'language': ''}

mycsv.csv 文件内容如下:
b'\xff\xfe"\x00\t\x00-N\xfdV"\x00\t\x00"\x00\t\x00^y\x1f\x82\'Y0W"\x00\t\x00"\x00\t\x00,\x00,\x00,\x00"\x00\t\x00\r\x00\n\x00"\x00\t\x001\x001\x001\x00"\x00\t\x00"\x00\t\x000\x001\x002\x003\x00"\x00\t\x00\r\x00\n\x00\r\x00\n\x00\r\x00\n\x00'

 

BOM

为了识别 Unicode 文件, Microsoft 建议所有的 Unicode 文件应该以U+FEFF字符开头. 这作为一个“特征符”或“字节顺序标记(byte-order mark, BOM)”来识别文件中使用的编码和字节顺序.

1.Linux/UNIX 并没有使用 BOM, 因为它会破坏现有的 ASCII 文件的语法约定. (大部情况下, 默认都是使用 UTF-8)

2.不同的编辑工具对BOM的处理也各不相同.

3.不同格式的文件使用的标记:

UTF-16: 0xFF 0xFE, 小节字序. 对 CSV 文件相当重要, 使用传统的方法, 即","分隔来形成单元格, 不能很好的显示数字(如数字前存有0)日期等格式, 使用此格式, 外加 "\t 作为分隔符, 可完美的解决此问题.

UTF-16le: 小节字序

UTF-16be: 0xFE 0xFF, 大节字序

UTF-8: 0xEF 0xBB 0xBF, 大部分文件都不使用此序列开头, 但 windows平台中的软件, 尤其是 Notepad(和开发工作相关) 和 Excel 会根据此 BOM 来确定编码, 否则使用本地的 windows 代码页.

UTF-32le: 0x00 0x00 0xFF 0xFE

UTF-32be: 0xFF 0xFE 0x00 0x00

把带有 BOM 的小节字序 UTF-16 称作「Unicode」而又不详细说明,这是微软的习惯.

 

python 文件编码格式指定

在源文件开头, 输入如以下所示代码即可:

# coding: UTF-8

# -*- coding: UTF-8 -*-

 

文件转换工具

utf8ToUtf16.py

import sys
import os


def main():
    filename = sys.argv[1] if len(sys.argv) > 1 else ""
    if not filename:
        return
    assert os.path.exists(filename), "{} not exists".format(filename)

    with open(filename, "r", encoding="utf-8") as fp:
        data = fp.read()

    if not data:
        return

    byte_data = data.encode("utf-16")

    with open(filename, "wb") as fp:
        fp.write(byte_data)


if __name__ == '__main__':
    main()

 

utf16ToUtf8.py

import sys
import os


def main():
    filename = sys.argv[1] if len(sys.argv) > 1 else "a"
    if not filename:
        return
    assert os.path.exists(filename), "{} not exists".format(filename)

    with open(filename, "r", encoding="utf-16") as fp:
        data = fp.read()

    if not data:
        return

    byte_data = data.encode("utf-8")
    byte_data = byte_data.replace(b"\r\n", b"\n")
    byte_data = byte_data.replace(b"\r\x00\n\x00", b"\n\x00")

    with open(filename, "wb") as fp:
        fp.write(byte_data)


if __name__ == '__main__':
    try:
        main()
    except FileNotFoundError as e:
        print(e)

 

posted @ 2020-03-22 08:04  阿Hai  阅读(380)  评论(0)    收藏  举报