【问题标题】:python cant parse csv as list ( utf-8 bom ) [duplicate]python无法将csv解析为列表(utf-8 bom)[重复]
【发布时间】:2022-08-16 03:21:25
【问题描述】:

编辑:这个问题Convert UTF-8 with BOM to UTF-8 with no BOM in Python 仅适用于 txt 文件,不能解决我的 csv 文件问题

我有两个 csv 文件

rtc_csv_file=\"csv_migration\\\\rtc-test.csv\"
ads_csv_file=\"csv_migration\\\\ads-test.csv\"

这是 ads-test.csv 文件(导致问题) https://easyupload.io/bk1krp 该文件是UTF-8 with BOM,这是我打开csv时vscode右下角的内容。

我正在尝试编写一个 python 函数来读取每一行,并将其转换为 dict 对象。

我的函数适用于第一个文件rtc-test.csv 很好,但是对于第二个文件ads-test.csv,当我使用utf-16 时出现错误UTF-16 stream does not start with BOM。所以我尝试使用utf-8utf-8-sig,但它只在每一行中读取为带有逗号分隔值的字符串。我不能用逗号分割,因为我将有包含逗号的列值。

我的 python 代码正确读取 rtc-test.csv 作为值列表。当使用带有 bom 的 utf-8 对 csv 进行编码时,如何将 ads-test.csv 作为值列表读取?

代码:

rtc_csv_file=\"csv_migration\\\\rtc-test.csv\"
ads_csv_file=\"csv_migration\\\\ads-test.csv\"

from csv import reader
import csv

# read in csv, convert to map organized by \'id\' as index root parent value
def read_csv_as_map(csv_filename, id_format, encodingVar):
    print(\'filename: \'+csv_filename+\', id_format: \'+id_format+\', encoding: \'+encodingVar)
    dict={}
    dict[\'rows\']={}
    try:
        with open(csv_filename, \'r\', encoding=encodingVar) as read_obj:
            csv_reader = reader(read_obj, delimiter=\'\\t\')
            csv_cols = None
            for row in csv_reader:
                if csv_cols is None:
                    csv_cols = row 
                    dict[\'csv_cols\']=csv_cols
                    print(\'csv_cols=\',csv_cols)
                else:
                    row_id_val = row[csv_cols.index(str(id_format))]
                    print(\'row_id_val=\',row_id_val)
                    dict[\'rows\'][row_id_val] = row
        print(\'done\')
        return dict
    except Exception as e:
        print(\'err=\',e)
        return {}

rtc_dict = read_csv_as_map(rtc_csv_file, \'Id\', \'utf-16\')
ads_dict = read_csv_as_map(ads_csv_file, \'ID\', \'utf-16\')

控制台输出:

filename: csv_migration\\rtc-test.csv, id_format: Id, encoding: utf-16
csv_cols= [\'Summary\', \'Status\', \'Type\', \'Id\', \'12NC\']
row_id_val= 262998
done
filename: csv_migration\\ads-test.csv, id_format: ID, encoding: utf-16
err= UTF-16 stream does not start with BOM

如果我尝试改用utf-16-le,我会得到一个不同的错误\'utf-16-le\' codec can\'t decode byte 0x22 in position 0: truncated data

如果我尝试使用utf-16-be,我会收到此错误:\'utf-16-be\' codec can\'t decode byte 0x22 in position 0: truncated data

为什么我的 python 代码不能读取这个 csv 文件?

  • 该文件未编码为 UTF-16,或者以某种方式未正确编码。你能分享文件的前几个字节(比如 10 或 12)吗?
  • 如果不以明确的表示形式查看数据的实际内容(代表性的,理想情况下的小样本),我们就无法告诉您正确的编码;有问题的字节的十六进制转储,每边都有几个字节的上下文通常就足够了,特别是如果你能告诉我们你认为这些字节应该代表什么。另见meta.stackoverflow.com/questions/379403/…
  • @snakecharmerb 我试图用十六进制编辑器查看文件以获取这些字节,但同时这里是有问题的文件:easyupload.io/bk1krp
  • 我的编辑器将该文件标识为带有 BOM 的 utf-8。
  • 如果我使用上面的函数解析文件,使用 encoding=utf-8delimiter=\'\\t\' ,当我到达 for row in csv_reader: 时,第一个结果是这个单个字符串 \\ufeffTitle,State,Work Item Type,ID,12NC。其中调用 rtc_csv_file 的函数会给出每行的列表。我希望以类似的方式解析有问题的广告文件,它可以获取每个列名的列表,而无需我用逗号等字符解析/拆分

标签: python csv encoding utf-8 ads


【解决方案1】:

您的 CSV 使用 UTF-8(默认)而不是 UTF-16 编码,因此将其作为编码传递:

ads_csv_file="ads-test.csv"

from csv import reader

# read in csv, convert to map organized by 'id' as index root parent value
def read_csv_as_map(csv_filename, id_format, encodingVar):
    print('filename: '+csv_filename+', id_format: '+id_format+', encoding: '+encodingVar)
    dict={}
    dict['rows']={}
    try:
        with open(csv_filename, 'r', encoding=encodingVar) as read_obj:
            csv_reader = reader(read_obj, delimiter='\t')
            csv_cols = None
            for row in csv_reader:
                if csv_cols is None:
                    csv_cols = row
                    dict['csv_cols']=csv_cols
                    print('csv_cols=',csv_cols)
                else:
                    row_id_val = row[csv_cols.index(str(id_format))]
                    print('row_id_val=',row_id_val)
                    dict['rows'][row_id_val] = row
        print('done')
        return dict
    except Exception as e:
        print('err=',e)
        return {}

ads_dict = read_csv_as_map(ads_csv_file, 'ID', 'utf-8')  # <- updated here

这是 CSV 供参考:

Title,State,Work Item Type,ID,12NC
"453560751251 TOOL, SQ-59 CORNER CLAMP","To Do","FRUPS","6034","453560751251"

【讨论】:

  • 如果我使用上面的函数解析文件,使用 encoding=utf-8 和 delimiter='\t' ,当我到达 csv_reader 中的 for row 时:第一个结果是这个单个字符串 \ufeffTitle,State,Work Item Type,ID,12NC. 。如果我调用 rtc_csv_file 的函数会给出每一行的列表。我希望以类似的方式解析有问题的广告文件,它可以获取每个列名的列表,而无需我用逗号等字符解析/拆分
  • @POVR2 您的文件格式错误或编码不是 UTF8 或 UTF16。使用这些编码中的每一种,我得到了相同的结果:utf-8utf-16-leutf-16-be。如果您知道您的文件只有逗号一个特殊字符,您可以将文件作为字符串读取并在\n, 上拆分
  • 拆分, 逗号字符可能适用于 col 标头,但我最终将拥有在描述/注释字段中包含逗号字符的 col 值。所以我不能可靠地用字符分割字符串。我试过 utf-8 和 utf-8-sig,但它们仍然只为每一行返回一个字符串,而不是分成一个列表
  • 您可以使用 encoding='utf-8-sig' 丢弃 BOM。
猜你喜欢
  • 2012-02-12
  • 2011-11-16
  • 2011-07-21
  • 1970-01-01
  • 2016-05-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-19
相关资源
最近更新 更多