首页 > 解决方案 > 使用 Python 在文件中查找非 ASCII 行或字符

问题描述

我正在尝试编写一个脚本来找出文件中的哪一行包含非 ASCII 字符(特别是“windows-1252”)。我写了这个脚本,希望当它到达包含错误字符的行时会出错:

import argparse

FILE_ENCODING = "windows-1252"


def get_failed_character(filepath):
    with open(filepath, encoding=FILE_ENCODING) as f:
        for num, line in enumerate(f, 1):
            try:
                line.strip()
            except:
                print(num)


if __name__ == '__main__':
    parser = argparse.ArgumentParser(
        description="Parse file."
    )
    parser.add_argument("--file", help="File name")
    args = parser.parse_args()

    get_failed_character(args.file)

标签: pythonencodingutf-8asciiargparse

解决方案


需要明确的是,cp1252 不是“ASCII 形式”,它是一个 ASCII 超集,所以你真的在这里寻找非 cp1252。

这里最简单的解决方案是只使用errors='replace'模式,然后在每一行中搜索替换字符:

def get_failed_character(filepath):
    with open(filepath, encoding=FLOW_FILE_ENCODING, errors='replace') as f:
        for num, line in enumerate(f, 1):
            if '\ufffd' in line:  # 0xFFFD is the Unicode replacement character
                print(num)

我会注意到这不是一种特别安全的检查方式;cp1252 对除了五个可能的字节之外的所有字节都有映射,因此其他一些 ASCII 超集编码中的文本很可能会通过此测试(它只会为 ASCII 范围之外的字节产生乱码)。这就是为什么 ASCII 超集(除了 UTF-8)是个坏主意的原因;在不提前知道编码的情况下,您可能会成功地将文本解码为垃圾,因为大多数超集可以将打算采用一种编码的数据映射到它们自己而不会出错,这对人类来说只是胡言乱语。您需要知道真正的编码,否则您只是在做出错误的猜测。

如果您的目标是找到非 ASCII cp1252 字符(您的问题措辞有点不清楚),这仍然有效,只需将参数更改为,encoding='ascii'以便所有非 ASCII 字符都成为替换字符。


推荐阅读