大文件逐行处理:提取匹配行后的指定行及时间戳
问题描述
有一个超过10GB的文本文件,格式示例如下:
DATASET OBJTYPE "mesh2d" BEGALD ND 58673 NC 116294 TIMEUNITS SECONDS TS 0 1.98849600e+08 0.000000000e+00 0.56000000e+00 0.200000000e+00 0.00000000e+00 0.100000000e+00 0.00000000e+00 0.00000000e+00 0.73400000e+00 TS 0 1.98853209e+08 0.00000000e+00 1.00500000e+00 4.00000000e+00 6.00000000e-05 9.00000000e+00 0.00000000e+00 0.00000000e+00 ... ENDDS
需要完成以下操作:
- 跳过文件开头直到
TIMEUNITS SECONDS行,从下一行开始处理 - 提取所有以
TS 0开头行中的时间戳(即该行第三个字段) - 提取每个
TS行之后的第2行、第5行、第8行的数据(TS行之后的第一行记为第1行,以此类推) - 由于文件过大,不能将整个文件读入内存,必须逐行处理
现有代码仅能提取时间戳,无法获取后续指定行的数据:
with open(r"file") as f: for line in f: if line.startswith("TIMEUNITS SECONDS"): break # 文件指针将从下一行开始 time=[] # 存储时间戳的列表 line2=[] # 或用 lines=[2,5,8] 统一管理 line5=[] line8=[] line for line in f: if line.startswith("TS"): print(line.strip()) # 输出所有TS行 ts=float(line.split()[2]) time.append(ts)
解决方案
核心思路是逐行遍历文件,识别到TS行后,通过计数器跟踪后续行的位置,提取目标行数据。全程仅在内存中保留当前行和少量状态变量,完全适配大文件场景。
改进后的代码如下:
def extract_ts_data(file_path): timestamps = [] ts_line2 = [] ts_line5 = [] ts_line8 = [] target_lines = {2, 5, 8} # 定义需要提取的TS后目标行号 current_ts_position = 0 # 记录当前是TS行后的第几行 with open(file_path, 'r') as f: # 跳过开头内容,直到找到TIMEUNITS SECONDS for line in f: if line.startswith("TIMEUNITS SECONDS"): break # 处理后续文件内容 for line in f: stripped_line = line.strip() # 遇到新的TS行,重置计数器并记录时间戳 if stripped_line.startswith("TS 0 "): timestamps.append(float(stripped_line.split()[2])) current_ts_position = 0 continue # 非TS行,计数器加1 current_ts_position += 1 # 判断当前行是否为目标行,提取数据 if current_ts_position in target_lines: try: value = float(stripped_line) except ValueError: # 处理无效数据,可根据需求调整逻辑 value = None if current_ts_position == 2: ts_line2.append(value) elif current_ts_position == 5: ts_line5.append(value) elif current_ts_position == 8: ts_line8.append(value) # 超过第8行后重置计数器,减少无效判断 if current_ts_position > 8: current_ts_position = 0 return timestamps, ts_line2, ts_line5, ts_line8 # 使用示例 timestamps, line2, line5, line8 = extract_ts_data("your_file_path.txt") # 可将结果保存到CSV文件 import csv with open("extracted_data.csv", 'w', newline='') as csvfile: writer = csv.writer(csvfile) writer.writerow(["Timestamp", "Line2", "Line5", "Line8"]) for t, l2, l5, l8 in zip(timestamps, line2, line5, line8): writer.writerow([t, l2, l5, l8])
代码说明
- 状态跟踪:用
current_ts_position变量记录当前行在TS行后的位置,遇到新TS行时重置为0 - 目标提取:通过集合
target_lines定义需要提取的行号,匹配时将数据转换为浮点数存入对应列表 - 内存优化:全程仅处理单行数据,结果列表按需追加,不会加载整个文件到内存
- 容错处理:添加
try-except捕获无效数据,避免程序崩溃 - 效率提升:计数器超过8后自动重置,减少不必要的判断逻辑
注意事项
- 若TS行后的行数不足8行(如接近文件末尾),对应列表会跳过缺失行,可根据需求调整缺失值的处理逻辑
- 若文件编码非默认UTF-8,需在
open函数中指定encoding参数 - 处理超大文件时,避免在循环内执行频繁IO操作(如打印),建议最后统一保存结果
内容的提问来源于stack exchange,提问作者ZVY545
相关产品推荐
相关产品推荐

