读取多个.dat文件最后一行并转换为CSV的技术求助
问题解决与代码修复
现有代码的核心问题
- 二进制读取导致格式混乱:用
'rb'模式打开文件得到bytes对象,直接写入CSV会把每个字节拆成单独元素,引发数据乱码、单元格合并问题。 - 数据未正确拆分与补全:读取的最后一行未按空格分割列,也没添加自定义行名作为首列。
- 初始化CSV冗余:空DataFrame导出会生成多余索引列,导致后续追加数据格式混乱。
- 循环逻辑冗余:
while循环完全可替换为if,无需多余嵌套。
修复后的代码方案(两种可选)
方案1:用csv模块直接写入(轻量高效)
from csv import writer import os.path allV = ['V0.8','V1','V1.1'] allD = ['D1','D2','D3'] allPhi = ['Phi1','Phi2','Phi3'] allZ = ['Z1','Z2','Z3'] allT = ['T1','T2','T3'] # 初始化CSV并写入表头(可根据实际需求修改列名) with open('All_Forces.csv', 'w', newline='') as f: writer_obj = writer(f) headers = ['RowName'] + [f'Col{i+1}' for i in range(25)] writer_obj.writerow(headers) # 遍历所有文件组合 for V in allV: for D in allD: for Phi in allPhi: for Z in allZ: for T in allT: datname = f"D:/{V}/{D}/{Phi}/{V}-{T}-{D}-{Phi}-{Z}/ForceDat/body_0_forces.dat" rowname = f"{V}_{T}_{D}_{Phi}_{Z}" if not os.path.isfile(datname): continue # 文件不存在直接跳过 # 高效读取最后一行(避免加载整个大文件) with open(datname, 'rb') as f: f.seek(-2, os.SEEK_END) while f.read(1) != b'\n': f.seek(-2, os.SEEK_CUR) last_line = f.readline().decode('utf-8').strip() # 按空格分割数据,过滤连续空格产生的空字符串 data_cols = [col for col in last_line.split(' ') if col] # 拼接行名与数据列 row_data = [rowname] + data_cols # 追加写入CSV with open('All_Forces.csv', 'a', newline='') as f: writer_obj = writer(f) writer_obj.writerow(row_data)
方案2:用Pandas(结构化数据处理更便捷)
import pandas as pd import os.path allV = ['V0.8','V1','V1.1'] allD = ['D1','D2','D3'] allPhi = ['Phi1','Phi2','Phi3'] allZ = ['Z1','Z2','Z3'] allT = ['T1','T2','T3'] data_list = [] for V in allV: for D in allD: for Phi in allPhi: for Z in allZ: for T in allT: datname = f"D:/{V}/{D}/{Phi}/{V}-{T}-{D}-{Phi}-{Z}/ForceDat/body_0_forces.dat" rowname = f"{V}_{T}_{D}_{Phi}_{Z}" if not os.path.isfile(datname): continue # 获取文件总行数,读取最后一行 with open(datname, 'r') as f: total_lines = sum(1 for _ in f) df_line = pd.read_csv(datname, sep='\s+', skiprows=total_lines-1, header=None) # 插入自定义行名列 df_line.insert(0, 'RowName', rowname) data_list.append(df_line) # 合并数据并导出CSV final_df = pd.concat(data_list, ignore_index=True) final_df.columns = ['RowName'] + [f'Col{i+1}' for i in range(25)] final_df.to_csv('All_Forces.csv', index=False)
关键修复说明
- 高效读取最后一行:通过文件指针定位到末尾换行符,避免加载整个大文件,适配10000+行的数据集。
- 数据分割优化:过滤分割后产生的空字符串,解决原文件连续空格导致的列数错误。
- CSV格式规范:用
newline=''避免Windows系统下出现多余空行,保证列分隔正确。 - 首列自定义:将生成的
rowname作为每行第一个元素,确保CSV首列符合需求。
内容的提问来源于stack exchange,提问作者CaptainWambo
相关产品推荐
相关产品推荐

