我有以utf-16 LE编码创建的临时文件列表。我需要合并这些临时文件,结果文件应该是utf-16。
我做了什么
for fd in source_fds_list:
with open(destination_url, 'ab') as destn_fd:
shutil.copyfileobj(fd, destn_fd)
fd.close()
它会导致目标文件中附加多个BOM。
如果临时文件是用不同的编码风格编写的,该怎么办?
除了使用文件读取手动检查BOM之外,是否存在更好的解决方案?
答案 0 :(得分:3)
shutil.copyfileobj()
复制所有数据,无论如何。 BOM只是文件中的数据,shutil
不是,也不会知道这些特定于文件格式的详细信息。
您可以自行轻松跳过BOM,但仍将大部分复制保留到shutil.copyfileobj()
:
import codecs
for fd in source_fds_list:
with open(destination_url, 'ab') as destn_fd:
with fd:
start = fd.read(2)
if start != codecs.BOM_UTF16_LE:
destn_fd.write(start)
shutil.copyfileobj(fd, destn_fd)
首先从源文件中读取前2个字节,shutil.copyfileobj()
将继续读取文件中的所有其他内容,跳过BOM。无论如何,所有shutil.copyfileobj()
都会调用data = source.read(buffer)
和destination.write(data)
。
如果您不知道用于输入文件的编解码器,则会遇到启发式问题。你可以测试各种codecs
BOM constants但是出现了误报的可能性;用UTF- *以外的编解码器编码的文件和初始字节看起来像的BOM:
for fd in source_fds_list:
with open(destination_url, 'ab') as destn_fd:
with fd:
start = fd.read(4)
if start not in (codecs.BOM_UTF32_LE, codecs.BOM_UTF32_BE):
if start[:3] != BOM_UTF8:
if start[:2] in (codecs.BOM_UTF16_LE, codecs.BOM_UTF16_BE):
# UTF-16 BOM, skip 2 bytes
start = start[2:]
else:
# UTF-8 BOM, skip 3 bytes
start = start[-1]
# Not a UTF-32 BOM, write read bytes (minus skipped bytes)
destn_fd.write(start)
shutil.copyfileobj(fd, destn_fd)