如何忽略UTF8编码的Unicode空白字符?

2024-09-30 10:39:58 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个包含以下信息的csv文件:

id  name    age     height  weight
1   x       12      11      124
2   y       13      23      432
3   z       14      43      1435

它存储在一个名为Workbook2.csv的文件中 我使用以下代码:

^{pr2}$

我得到以下结果:

{'weight': '124', '\xef\xbb\xbfid': '1', 'height ': '11', 'age   ': '12', 'name ': 'x'}
{'weight': '432', '\xef\xbb\xbfid': '2', 'height ': '23', 'age   ': '13', 'name ': 'y'}
{'weight': '1435', '\xef\xbb\xbfid': '3', 'height ': '43', 'age   ': '14', 'name ': 'z'}

我想知道如何将此输出更新为字典。 我还想知道如何忽略使用UTF-8编码的unicode字符,如果有一个过滤器可以用来消除它们。在


Tags: 文件csv代码name信息idage字典
3条回答

有一个kwarg skipinitialspace,但我从C代码中验证了它只查找“”。在

两种可能性:

  1. 子类DictReader以添加一些代码以去掉空格
  2. 在将文件中的行传递给听写器之前,请先按摩这些行。在

(2)的一个例子是:

import io
with io.open('Workbook2.csv', 'r', encoding='utf8') as infile:
    ipFile = csv.DictReader((x.replace(u"\uFEFF", u" ") for x in infile))
....

我认为这个结果显然被误解了。在

DictReader从第一行获取字段名,第一列(不可见BOM之后的列)就是“id”。这就是为什么id字段现在在每个记录中都预先添加了BOM。在

在Python2.7和3.6中,我必须使用方言csv.excel_tab来将制表符解释为分隔符。在

您的输入数据/csv文件是绝对可以的,因为只有一个BOM在开始(它应该在那里)。你只需要在阅读前把BOM去掉。在

例如这样:

from codecs import BOM_UTF8
csv_file = open('test2.csv', 'rU')
csv_file.seek(len(BOM_UTF8))
ipFile = csv.DictReader(csv_file, dialect=csv.excel_tab)

您的输入数据在的每一行中都包含UTF-8 BOM sequences。不管生成这个文件的是什么,它似乎一直在使用utf-8-sig编解码器或非Python等价物一次添加一行数据。BOM(如果使用的话)应该是文件中的第一个字符,不能在其他任何地方使用。您的数据已损坏,如果您可以在源代码处修复此问题,请这样做。在

但是,有一种方法可以在您阅读时修复此问题。csv模块读取的“file”可以是任何在迭代时生成行的内容。首先使用生成器过滤文件行:

from codecs import BOM_UTF8

def bom_filter(lines):
    for line in lines:
        if line.startswith(BOM_UTF8):
            line = line[len(BOM_UTF8):]
        yield line

然后,在将文件传递给DictReader()对象之前,先通过过滤器:

^{pr2}$

演示:

>>> from io import BytesIO
>>> import csv
>>> from codecs import BOM_UTF8
>>> def bom_filter(lines):
...     for line in lines:
...         if line.startswith(BOM_UTF8):
...             line = line[len(BOM_UTF8):]
...         yield line
...
>>> demofile = BytesIO('''\
... \xef\xbb\xbfid,name,age,height,weight
... \xef\xbb\xbf1,x,12,11,124
... \xef\xbb\xbf2,y,13,23,432
... \xef\xbb\xbf3,z,14,43,1435
... ''')
>>> ipFile = csv.DictReader(bom_filter(demofile))
>>> for row in ipFile:
...     print row
...
{'age': '12', 'height': '11', 'id': '1', 'weight': '124', 'name': 'x'}
{'age': '13', 'height': '23', 'id': '2', 'weight': '432', 'name': 'y'}
{'age': '14', 'height': '43', 'id': '3', 'weight': '1435', 'name': 'z'}

在python3中,csv模块接受Unicode字符串输入(与bytestrings相反,因此现在需要查找解码结果,即U+FEFF零宽度空间码位。要使代码在任何一个Python版本上都能正常工作,您必须在行首替换要测试的内容:

import sys
to_filter = u'\ufeff'
if sys.version_info < (3,):
    to_filter = to_filter.encode('utf8')

def bom_filter(lines):
    for line in lines:
        if line.startswith(to_filter):
            line = line[len(to_filter):]
        yield line

相关问题 更多 >

    热门问题