设置脚本以在Python中的纯文本文件中自动检测字符编码?

时间:2010-06-14 02:27:15

标签: python character-encoding replace

我已经设置了一个基本上在纯文本文档上进行大规模查找和替换的脚本。

目前,只要在脚本中指定了编码(示例代码),它就可以使用ASCII,UTF-8和UTF-16(可能还有其他人,但我只测试了这三个)编码文档。以下指定UTF-16)。

有没有办法让脚本自动检测输入文件中使用了哪些字符编码,并自动设置输出文件的字符编码与输入文件中使用的编码相同?

findreplace = [
('term1', 'term2'),
]    

inF = open(infile,'rb')
    s=unicode(inF.read(),'utf-16')
    inF.close()

    for couple in findreplace:
        outtext=s.replace(couple[0],couple[1])
        s=outtext

    outF = open(outFile,'wb')
    outF.write(outtext.encode('utf-16'))
    outF.close()

谢谢!

3 个答案:

答案 0 :(得分:3)

从链接J.F. Sebastian发布:试试chardet

请记住,一般情况下,不可能100%可靠地检测每个输入文件的字符编码 - 换句话说,有可能的输入文件可以被解释为几个任何一个字符编码,可能无法分辨哪一个实际被使用。 chardet使用了一些启发式方法,并给出了一个置信度,表明它确切地告诉你的字符编码确实是正确的。

答案 1 :(得分:3)

一些观察和问题:

(1)ASCII是UTF-8的一个子集,在某种意义上说,如果一个文件可以使用ASCII成功解码,那么它可以使用UTF-8成功解码。因此,您可以从列表中删除ASCII。

(2)findreplace中的两个术语是否包含非ASCII字符?请注意,回答“是”表示将输出文件写入与输入相同的字符集中的目标可能很难/无法实现。

(3)为什么不在SAME handle-all-Unicode-characters编码中写入所有输出文件,例如UTF-8?

(4)UTF-8文件是否有BOM?

(5)您认为需要处理哪些其他字符集?

(6)您调用UTF-16的四种可能性中的哪一种(UTF-16LE / UTF-16BE)x(BOM /无BOM)?请注意,我故意不要在代码中出现'utf-16'来推断任何事情。

(7)请注意,如果没有BOM,chardet不会检测到UTF-16xE。 chardet有非* x和旧字符集的其他盲点。

更新以下是一些代码片段,您可以使用这些代码片段来确定“ANSI”是什么,并尝试使用受限制的编码列表进行解码。注意:这假设是Windows环境。

# determine "ANSI"
import locale
ansi = locale.getdefaultlocale()[1] # produces 'cp1252' on my Windows box.

f = open("input_file_path", "rb")
data = f.read()
f.close()

if data.startswith("\xEF\xBB\xBF"): # UTF-8 "BOM"
    encodings = ["utf-8-sig"]
elif data.startswith(("\xFF\xFE", "\xFE\xFF")): # UTF-16 BOMs
    encodings = ["utf16"]
else:
    encodings = ["utf8", ansi, "utf-16le"]
# ascii is a subset of both "ANSI" and "UTF-8", so you don't need it.
# ISO-8859-1 aka latin1 defines all 256 bytes as valid codepoints; so it will
# decode ANYTHING; so if you feel that you must include it, put it LAST.
# It is possible that a utf-16le file may be decoded without exception
# by the "ansi" codec, and vice versa.
# Checking that your input text makes sense, always a very good idea, is very 
# important when you are guessing encodings.

for enc in encodings:
    try:
        udata = data.decode(enc)
        break
    except UnicodeDecodeError:
        pass
else:
    raise Exception("unknown encoding")

# udata is your file contents as a unicode object
# When writing the output file, use 'utf8-sig' as the encoding if you
# want a BOM at the start. 

答案 2 :(得分:1)

不,没有。您必须在文件本身或外部源中编码该知识。

有一些启发式,可以通过字节顺序频率的统计分析来猜测文件的编码;但我不会将它们用于任何关键任务数据。