在Python中从gzip格式的CSV删除BOM

发布于 2021-01-29 18:03:32

我正在使用以下代码解压缩并保存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 <module>
    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中?

关注者
0
被浏览
48
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    首先,您需要解码文件内容,而不是对其进行编码。

    其次,该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,而不仅仅是第一行。如果您不需要保留其他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
    


知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看