使用ijson解析cp1252编码大JSON文件遇编码错误如何处理
报错核心原因
触发编码错误是两个问题叠加导致:
- 用文本模式
r打开文件时手动指定了cp1252做第一层解码,但ijson默认期望接收二进制字节流,会对传入内容做第二层UTF-8解码,双重解码逻辑直接冲突 - 没有在ijson的解析参数里显式指定文件编码,ijson默认按UTF-8解析,遇到非UTF-8编码的字节(比如代码里
hændelse的æ字符在cp1252里的编码就是0xe6,不符合UTF-8编码规则)就会抛出解码错误。
解决步骤
- 第一步:先确认文件实际编码,不要靠猜测。47GB的文件不需要全量读取,取前1MB内容检测即可:
import chardet with open("C:/Path/To/Json/JSON_20220703180000.json", "rb") as f: sample = f.read(1024 * 1024) print(chardet.detect(sample))
如果没有安装chardet,执行pip install chardet即可,轻量无依赖。运行后输出的encoding字段就是文件的真实编码,常见的丹麦语JSON文件编码可能是cp1252、iso-8859-1、utf-8-sig(带BOM的UTF-8)。
- 第二步:用二进制模式打开文件,把编码参数传给ijson而非open函数,全程走流式解析不占用额外内存:
import ijson # 二进制模式打开,不要在open里指定encoding with open("C:/Path/To/Json/JSON_20220703180000.json", "rb") as json_file: # 把上一步检测到的编码替换下面的cp1252即可 objects = ijson.items(json_file, 'SagList.item', encoding='cp1252') byggesag = (o for o in objects if o['hændelse'] == 'Byggesag') # 后续直接遍历byggesag做业务处理即可 # for item in byggesag: # 自定义处理逻辑
容错处理方案
如果文件存在少量损坏的非法编码字节导致解析中断,可以给ijson加错误容错参数,用替换符兜底非法字节:
import ijson with open("C:/Path/To/Json/JSON_20220703180000.json", "rb") as json_file: objects = ijson.items( json_file, 'SagList.item', encoding='cp1252', errors='replace' # 非法字节替换为�,不会中断解析流程 ) byggesag = (o for o in objects if o['hændelse'] == 'Byggesag')
注意事项
- 绝对不要用文本模式打开大文件传给ijson,除了解码冲突,文本模式的预读缓冲还会额外占用内存,失去流式解析的优势
- 如果检测到编码是带BOM的UTF-8,encoding参数填
utf-8-sig即可自动跳过BOM头 - 不要尝试一次性加载47GB文件到内存做编码转换,流式解析+ijson原生编码处理的内存占用可以稳定在几十MB级别。
内容的提问来源于stack exchange,提问作者TomGeo
相关产品推荐
相关产品推荐

