Python TextIOWrapper读取文件遇特殊行中断无法读取完整文件
解决方案
问题原因
读取中断并非第92行文本本身存在特殊转义字符,通常是该行前后混入了\x1a(Windows平台Ctrl+Z对应的文件结束标识),Python默认会将该字符识别为EOF终止读取。你之前使用二进制模式未生效,是因为调用readlines()全量加载时没有对异常字节做容错处理,遇到伪造的EOF标识就会截断读取流程。
方案1:正向容错读取(需读取文件靠前内容时使用)
不要用readlines()一次性加载全量内容,打开文件时指定errors='ignore'忽略解码异常,直接迭代文件对象逐行读取即可,遇到异常字节会自动跳过不会中断:
import os txt_file = os.path.join(dir_register, 'messag') cpu_time = None with open(txt_file, 'r', encoding='utf-8', errors='ignore') as f: for line in f: if 'Total CPU time' in line: cpu_time = float(line.split()[4]) break # 找到目标后直接退出,无需读取后续内容
如果必须用二进制模式,读取后对每一行手动指定errors='ignore'解码即可,效果一致。
方案2:尾部反向读取(仅提取末尾CPU时间时优先用)
由于目标数据在文件近尾部,反向读取不需要遍历前面的内容,可完全绕开第92行的异常段,读取效率更高:
import os txt_file = os.path.join(dir_register, 'messag') cpu_time = None block_size = 2048 # 每次从尾部读取2KB块,可根据实际行长度调整 with open(txt_file, 'rb') as f: f.seek(0, os.SEEK_END) file_size = f.tell() prev_tail = b'' # 从尾往前逐块扫描 for block_idx in range(file_size // block_size + 1): read_pos = max(file_size - (block_idx + 1) * block_size, 0) f.seek(read_pos) current_block = f.read(block_size) + prev_tail lines = current_block.split(b'\n') # 倒序遍历当前块的行,找目标字段 for line in reversed(lines): if b'Total CPU time' in line: cpu_time = float(line.split()[4]) break if cpu_time is not None: break # 保存块首截断的不完整行,和下一个读取块拼接 prev_tail = lines[0]
方案选择建议
- 若后续还需提取文件前部的其他数据,选用方案1即可,
errors='ignore'参数已经能覆盖绝大多数异常字符导致的读取中断问题; - 若仅需提取CPU时间字段,优先选方案2,不需要处理文件前部的异常内容,大文件下速度优势更明显。
内容的提问来源于stack exchange,提问作者SirFritz
相关产品推荐
相关产品推荐

