在Python中从gzip'ed CSV中删除BOM

 沫小兮 发布于 2023-02-06 19:23

我正在使用以下代码解压缩并保存CSV文件:

with gzip.open(filename_gz) as f:
    file = open(filename, "w");
    output = csv.writer(file, delimiter = ',')
    output.writerows(csv.reader(f, dialect='excel', delimiter = ';'))

一切似乎都有效,除了文件中的第一个字符是意外的.谷歌搜索似乎表明它是由于文件中的BOM.

我已经读过在utf-8-sig中编码内容应该可以解决这个问题.但是,添加:

.read().encoding('utf-8-sig')

到csv.reader中的f失败:

File "ckan_gz_datastore.py", line 16, in 
    output.writerows(csv.reader(f.read().encode('utf-8-sig'), dialect='excel', delimiter = ';'))
File "/usr/lib/python2.7/encodings/utf_8_sig.py", line 15, in encode
    return (codecs.BOM_UTF8 + codecs.utf_8_encode(input, errors)[0], len(input))
UnicodeDecodeError: 'ascii' codec can't decode byte 0xef in position 0: ordinal not in range(128)

如何删除BOM并将内容保存为正确的utf-8?

1 个回答
  • 首先,您需要解码文件内容,而不是编码它们.

    其次,csv模块不喜欢Python 2.7中的unicode字符串,所以解码了你需要转换回utf-8的数据.

    最后,csv.reader在文件的行上传递迭代,而不是在其中包含换行符的大字符串.

    所以:

    csv.reader(f.read().decode('utf-8-sig').encode('utf-8').splitlines())
    

    但是,您可能会认为只是手动删除BOM更简单/更有效:

    def remove_bom(line):
        return line[3:] if line.startswith(codecs.BOM_UTF8) else line
    
    csv.reader((remove_bom(line) for line in f), dialect = 'excel', delimiter = ';')
    

    这是微妙的不同,因为它从任何以1开头的行中移除BOM,而不是仅从第一行开始.如果您不需要保留其他物料清单,那么您可以使用以下方法修复它:

    def remove_bom_from_first(iterable):
        f = iter(iterable)
        firstline = next(f, None)
        if firstline is not None:
            yield remove_bom(firstline)
            for line in f:
                yield f
    

    2023-02-06 19:26 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有