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

设置脚本以自动检测Python中纯文本文件中的字符编码?,python,character-encoding,replace,Python,Character Encoding,Replace,我已经建立了一个脚本,基本上可以对纯文本文档进行大规模查找和替换 目前,只要在脚本中指定了编码(下面的示例代码指定了UTF-16),它就可以很好地处理ASCII、UTF-8和UTF-16(可能还有其他,但我只测试了这三种)编码文档 是否有办法使脚本自动检测输入文件中使用的字符编码,并自动将输出文件的字符编码设置为与输入文件中使用的编码相同 findreplace = [ ('term1', 'term2'), ] inF = open(infile,'rb') s=unicod

我已经建立了一个脚本,基本上可以对纯文本文档进行大规模查找和替换

目前,只要在脚本中指定了编码(下面的示例代码指定了UTF-16),它就可以很好地处理ASCII、UTF-8和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()

谢谢

没有。您必须在文件本身内部或从外部来源对这些知识进行编码


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

来自J.F.Sebastian发布的链接:试试看


请记住,一般来说,不可能100%可靠地检测每个输入文件的字符编码-换句话说,有可能的输入文件可以与多个字符编码中的任何一个进行同样好的解释,并且可能无法判断实际使用的是哪一个。chardet使用了一些启发式方法,并为您提供了一个置信水平,表明它告诉您的字符编码是否确实正确。

一些观察和问题:

(1) ASCII是UTF-8的一个子集,即如果可以使用ASCII成功解码文件,则可以使用UTF-8成功解码文件。这样您就可以从列表中划掉ASCII

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

(3) 为什么不在同一个句柄中写入所有输出文件所有Unicode字符编码,例如UTF-8

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

(5) 您合理地期望需要处理哪些其他字符集

(6) 四种可能性(UTF-16LE/UTF-16BE)x(BOM/无BOM)中,您称之为UTF-16的是哪一种?请注意,我无意从代码中是否存在“utf-16”来推断任何东西

(7) 请注意,
chardet
不会检测到没有BOM的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. 

相关的“Python和编码”对不起,我对这一切有点生疏!正如您在3中所建议的,我现在对其进行了更改,使其始终以UTF-8输出。因为使用这个的人使用的是Windows机器,我想UTF-8文件会有一个BOM表。我计划将脚本分发给非技术爱好者,因此它基本上只需要接受各种默认字符集,没有什么特别的。所以为了响应5,它可能需要ANSI、ASCII、UTF8、UTF16和ISO 8859-1。@Haidon:请回答Q2和Q6。当被要求澄清时,编辑你的问题而不是评论。是什么让你认为ISO-8859-1是“Windows上的默认字符集”?普通Windows用户如何创建这样的文件?