我收到了一些编码的文本,但我不知道使用了什么字符集.有没有办法使用Python确定文本文件的编码?如何检测文本文件的编码/代码页处理C#.
始终正确地检测编码是不可能的.
(来自chardet FAQ :)
但是,某些编码针对特定语言进行了优化,语言不是随机的.一些字符序列一直弹出,而其他序列没有任何意义.一个英语流利的人打开一份报纸并发现"txzqJv 2!dasd0a QqdKjvz"会立刻发现这不是英文(即使它完全由英文字母组成).通过研究大量"典型"文本,计算机算法可以模拟这种流畅性,并对文本语言做出有根据的猜测.
有一个chardet库使用该研究来尝试检测编码.chardet是Mozilla中自动检测代码的一个端口.
您也可以使用UnicodeDammit.它将尝试以下方法:
在文档本身中发现的编码:例如,在XML声明中或(对于HTML文档)的http-equiv META标记.如果Beautiful Soup在文档中找到这种编码,它会从头开始再次解析文档并尝试新编码.唯一的例外是如果您明确指定了编码,并且该编码实际上有效:那么它将忽略它在文档中找到的任何编码.
通过查看文件的前几个字节来嗅探编码.如果在此阶段检测到编码,则它将是UTF-*编码,EBCDIC或ASCII之一.
如果安装了chardet库,则会对其进行嗅探.
UTF-8
Windows的1252
计算编码的另一个选择是使用 libmagic(这是file命令背后的代码 ).有大量的python绑定可用.
生成在文件源树中的python绑定可以作为 python-magic(或python3-magic)debian包使用.它可以通过执行以下操作来确定文件的编码:
import magic
blob = open('unknown-file').read()
m = magic.open(magic.MAGIC_MIME_ENCODING)
m.load()
encoding = m.buffer(blob) # "utf-8" "us-ascii" etc
在pypi上有一个同名但不兼容的python-magic pip包也可以使用libmagic
.它还可以通过以下方式获得编码:
import magic
blob = open('unknown-file').read()
m = magic.Magic(mime_encoding=True)
encoding = m.from_buffer(blob)
一些编码策略,请取消注释:
#!/bin/bash # tmpfile=$1 echo '-- info about file file ........' file -i $tmpfile enca -g $tmpfile echo 'recoding ........' #iconv -f iso-8859-2 -t utf-8 back_test.xml > $tmpfile #enca -x utf-8 $tmpfile #enca -g $tmpfile recode CP1250..UTF-8 $tmpfile
您可能希望通过以循环形式打开和读取文件来检查编码...但您可能需要先检查文件大小:
encodings = ['utf-8', 'windows-1250', 'windows-1252' ...etc] for e in encodings: try: fh = codecs.open('file.txt', 'r', encoding=e) fh.readlines() fh.seek(0) except UnicodeDecodeError: print('got unicode error with %s , trying different encoding' % e) else: print('opening the file with encoding: %s ' % e) break
这是一个读取和获取面值chardet
编码预测的示例,n_lines
在文件很大的情况下从文件中读取.
chardet
还给你一个概率(即confidence
)它的编码预测(没有看到它们是如何得出的),它与它的预测一起返回chardet.predict()
,所以如果你愿意,你可以以某种方式工作.
def predict_encoding(file_path, n_lines=20): '''Predict a file's encoding using chardet''' import chardet # Open the file as binary data with open(file_path, 'rb') as f: # Join binary lines for specified number of lines rawdata = b''.join([f.readline() for _ in range(n_lines)]) return chardet.detect(rawdata)['encoding']