这里有两个问题。我有一组文件,它们通常是带有BOM的UTF-8。我想把它们转换成没有BOM的UTF-8 (最好是就地)。看起来codecs.StreamRecoder(stream, encode, decode, Reader, Writer, errors)
会处理这件事。但我真的看不到任何关于用法的好例子。这是处理这个问题的最好方法吗?
source files:
Tue Jan 17$ file brh-m-157.json
brh-m-157.json: UTF-8 Unicode (with BOM) text
此外,如果我们可以在不明确知道的情况下处理不同的输入编码(参见ASCII和UTF-16),那将是最理想的。看起来这一切都应该是可行的。有没有一个解决方案可以接受任何已知的Python编码和输出为UTF-8而不需要BOM?
从下面编辑1个提议的解决方案(谢谢!)
fp = open('brh-m-157.json','rw')
s = fp.read()
u = s.decode('utf-8-sig')
s = u.encode('utf-8')
print fp.encoding
fp.write(s)
这会给我以下错误:
IOError: [Errno 9] Bad file descriptor
新闻快讯
我在评论中被告知,错误是我以'rw‘模式打开文件,而不是'r+'/'r+b',所以我最终应该重新编辑我的问题并删除已解决的部分。
发布于 2012-01-18 00:47:57
fp = open("file.txt")
s = fp.read()
u = s.decode("utf-8-sig")
这将为您提供一个不带物料清单的unicode
字符串。然后,您可以使用
s = u.encode("utf-8")
将一个普通的UTF8编码的字符串返回到s
。如果你的文件很大,那么你应该避免将它们全部读入内存。BOM在文件的开头只有三个字节,因此您可以使用以下代码将它们从文件中剥离出来:
import os, sys, codecs
BUFSIZE = 4096
BOMLEN = len(codecs.BOM_UTF8)
path = sys.argv[1]
with open(path, "r+b") as fp:
chunk = fp.read(BUFSIZE)
if chunk.startswith(codecs.BOM_UTF8):
i = 0
chunk = chunk[BOMLEN:]
while chunk:
fp.seek(i)
fp.write(chunk)
i += len(chunk)
fp.seek(BOMLEN, os.SEEK_CUR)
chunk = fp.read(BUFSIZE)
fp.seek(-BOMLEN, os.SEEK_CUR)
fp.truncate()
它打开文件,读取一个块,并将其写出到文件中,比读取它的位置早3个字节。该文件将被就地重写。因为更简单的解决方案是将较短的文件写入一个新文件,如newtover's answer。这会更简单,但在短时间内使用两倍的磁盘空间。
至于猜测编码,那么您可以从最具体到最不具体依次遍历编码:
def decode(s):
for encoding in "utf-8-sig", "utf-16":
try:
return s.decode(encoding)
except UnicodeDecodeError:
continue
return s.decode("latin-1") # will always work
UTF-16编码的文件不能解码为UTF-8,因此我们首先尝试使用UTF-8。如果失败,那么我们尝试使用UTF-16。最后,我们使用拉丁-1-这将始终有效,因为所有256个字节都是拉丁-1中的合法值。在这种情况下,您可能希望返回None
,因为它实际上是一种后备,并且您的代码可能希望更小心地处理这一点(如果可以)。
发布于 2015-10-23 10:57:04
在Python3中很简单:读取文件并使用utf-8
编码重写它:
s = open(bom_file, mode='r', encoding='utf-8-sig').read()
open(bom_file, mode='w', encoding='utf-8').write(s)
发布于 2012-01-18 01:03:45
import codecs
import shutil
import sys
s = sys.stdin.read(3)
if s != codecs.BOM_UTF8:
sys.stdout.write(s)
shutil.copyfileobj(sys.stdin, sys.stdout)
https://stackoverflow.com/questions/8898294
复制相似问题