You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python如何不改变编码替换二进制EDF文件中的指定字符

问题描述

需要对二进制编码的EDF文件做字符替换,将文件第一行中所有出现的°字符替换为?。

不指定二进制读取模式打开文件时会抛出如下异常:

UnicodeDecodeError: 'utf-8' codec can't decode byte 0xb0 in position 3008: invalid start byte

触发异常的代码:

with open('heartbeat-baseline-700001.edf') as fin:
    lines = fin.readlines()

自行编写的替换代码运行后异常:生成的文件大小从原文件的79MB骤降至7KB,完全无法正常使用,代码如下:

with open("heartbeat-baseline-700001.edf", "rb") as text_file:
    lines = text_file.readlines()
    lines[1] = lines[1].replace(str.encode('°'), str.encode('?'))
    for i,line in enumerate(lines):
        with open('heartbeat-baseline-700001_python.edf', 'wb') as fout:
            fout.write(line)
问题原因

代码存在三个核心问题:

  • 行索引错误:Python列表下标从0开始计数,需要修改的第一行内容对应lines[0],修改lines[1]实际操作的是文件第二行,完全没有命中目标修改位置。
  • 写入逻辑错误:打开输出文件的逻辑被放在了遍历行的循环内部,且打开模式为wb(覆盖写入),每次循环都会清空文件之前写入的内容,循环结束后文件中仅会保留最后一行的内容,这就是文件大小骤降的根本原因。
  • 编码隐患:直接调用str.encode('°')会使用系统默认编码做转换,不同运行环境下生成的字节序列可能不一致,很容易出现匹配不到目标字符的问题。
正确实现方案

EDF是格式固定的二进制文件,根据规范,文件第一行头信息固定为256字节长度,不需要将整个79MB文件全量读入内存拆分行,仅需要读取前256字节做替换,剩余内容直接流式复制即可,全程二进制操作不会破坏文件原有编码和结构,实现代码如下:

# 同时以二进制模式打开源文件和目标文件
with open("heartbeat-baseline-700001.edf", "rb") as fin, open("heartbeat-baseline-700001_python.edf", "wb") as fout:
    # 仅读取第一行固定长度的头信息做替换,EDF头默认使用latin1单字节编码
    first_header = fin.read(256)
    replaced_header = first_header.replace('°'.encode('latin1'), '?'.encode('latin1'))
    fout.write(replaced_header)
    # 剩余所有二进制内容原封不动写入目标文件
    fout.write(fin.read())

说明:选择latin1编码做字节转换是因为EDF规范明确要求头字段使用兼容ASCII的latin1(ISO-8859-1)编码,°在该编码下对应的单字节正好是报错信息中提到的0xb0,可以保证100%匹配目标字符,不会出现编码不匹配的问题。

内容的提问来源于stack exchange,提问作者Warren Manuel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 02:46:00