如何按行数拆分TSV文件?解决charmap编码解码错误
解决TSV文件拆分时的编码解码错误问题
先帮你理清楚当前的问题:你要把40万行的TSV文件拆成4个各10万行的文件(注意你代码里存的是.tsv,如果需要最终输出CSV,后面可以调整后缀),但运行代码时碰到了编码解析错误——这是因为Windows默认的文件编码(charmap)没法识别你文件里的特殊字符。
先看你原来的代码:
csvfile = open('./world_formatted.tsv', 'r').readlines() filename = 1 for i in range(len(csvfile)): if i % 100000 == 0: open(str(filename) + '.tsv', 'w+').writelines(csvfile[i:i+100000]) filename += 1
运行后触发的错误:
'charmap' codec can't decode byte 0x8d in position 7316: character maps to
问题根源
这个错误的核心是打开文件时没指定正确的字符编码。当你用open()不带encoding参数时,Python会调用系统默认编码(Windows下多为cp1252这类charmap编码),而你的TSV文件里包含了该编码不支持的字符(比如0x8d),直接导致解码失败。
另外你原来的代码还有两个小隐患:
- 一次性把40万行全部读入内存,虽然当前量级不算特别大,但如果文件再扩容,会占用过多内存资源;
- 打开文件后没有显式关闭,可能导致资源泄漏或写入不完整。
改进后的解决方案
我给你调整了代码,既解决编码问题,又优化了内存使用:
source_file_path = './world_formatted.tsv' chunk_size = 100000 current_chunk = [] file_counter = 1 # 用with语句自动管理文件资源,避免忘记关闭 with open(source_file_path, 'r', encoding='utf-8', errors='replace') as source_file: for line in source_file: current_chunk.append(line) # 当当前块达到10万行时写入文件 if len(current_chunk) == chunk_size: # 要输出CSV的话,把后缀改成.csv即可 with open(f'{file_counter}.tsv', 'w', encoding='utf-8') as output_file: output_file.writelines(current_chunk) current_chunk = [] file_counter += 1 # 处理最后不足10万行的剩余内容 if current_chunk: with open(f'{file_counter}.tsv', 'w', encoding='utf-8') as output_file: output_file.writelines(current_chunk)
代码细节说明
- 指定编码:打开文件时加上
encoding='utf-8',如果utf-8不适用,你可以先用chardet库检测文件实际编码:
然后把import chardet with open(source_file_path, 'rb') as f: result = chardet.detect(f.read(10000)) print(result['encoding']) # 输出文件的真实编码,比如gbk、utf-16等encoding参数改成检测到的值即可。 - errors='replace':可选参数,如果碰到编码无法解析的字符,会用
�替换,避免程序直接中断。 - 逐行读取:不再一次性加载所有内容到内存,逐行处理更节省资源。
- with语句:自动处理文件的打开和关闭,比手动调用
close()更安全可靠。 - 剩余行处理:确保最后不足10万行的内容也能被正常写入文件。
如果你确实需要把TSV转成CSV,只需要把输出文件的后缀改成.csv,同时把每行的制表符替换成逗号——比如把current_chunk.append(line)改成current_chunk.append(line.replace('\t', ','))。
内容的提问来源于stack exchange,提问作者Code explore
相关产品推荐
相关产品推荐

