我正在使用以下代码解压缩并保存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?
解决方法:
首先,您需要解码文件内容,而不是编码它们.
其次,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
标签:byte-order-mark,python,csv 来源: https://codeday.me/bug/20190927/1823956.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。