如何读取指定文件夹内所有文件并按时间戳排序合并为单个文件
多结构化文件按时间戳排序合并实现
核心实现逻辑
- 扫描指定目标文件夹,过滤所有需要处理的普通文件,跳过临时文件、子目录
- 逐行读取所有文件的内容,跳过每个文件自带的表头行,避免合并后出现重复表头
- 解析每行首列的TimeStamp字段为可比较的时间数值,以该字段为排序键完成全量数据的全局排序
- 将单份表头 + 排序后的全量数据写入指定的单个输出文件
方案1:Python 轻量化实现
适用场景:待合并的所有文件总大小在内存可承载范围内(<10G),无需额外依赖即可快速实现。
import os import csv from datetime import datetime def merge_files_by_timestamp(input_dir: str, output_file: str): # 匹配示例中的时间戳格式:"2020-01-22 11:22:33.323" ts_format = "%Y-%m-%d %H:%M:%S.%f" all_sorted_rows = [] global_header = None # 遍历目录下所有文件 for entry in os.scandir(input_dir): if not entry.is_file(): continue # 可按需增加文件后缀过滤规则,比如仅处理.log/.csv后缀文件 with open(entry.path, 'r', encoding='utf-8') as f: reader = csv.reader(f) current_file_header = next(reader, None) if global_header is None: global_header = current_file_header # 逐行解析,缓存可排序的时间戳和原始内容 for row in reader: if not row or len(row) < 3: continue ts_str = row[0].strip() try: parsed_ts = datetime.strptime(ts_str, ts_format) all_sorted_rows.append((parsed_ts, row)) except ValueError: # 自动跳过格式不匹配的异常行 continue # 按时间戳全局排序 all_sorted_rows.sort(key=lambda item: item[0]) # 写出合并后的有序文件 with open(output_file, 'w', encoding='utf-8', newline='') as f: writer = csv.writer(f) if global_header: writer.writerow(global_header) for _, row_content in all_sorted_rows: writer.writerow(row_content) # 调用示例 if __name__ == "__main__": merge_files_by_timestamp(input_dir="./input_folder_path", output_file="./merged_result.csv")
方案2:Java 实现(兼容原有两文件合并逻辑)
适用场景:基于已有Java两文件排序合并代码扩展,无需重写原有时间戳比较逻辑,仅增加目录遍历、多文件加载能力即可适配。
import java.io.*; import java.nio.file.*; import java.sql.Timestamp; import java.util.*; import java.util.stream.Stream; public class TimestampFileMerger { public static void mergeAllFiles(String inputDirPath, String outputPath) throws IOException { List<String[]> sortableData = new ArrayList<>(); String[] globalHeader = null; // 遍历指定目录下的所有普通文件 try (Stream<Path> pathStream = Files.walk(Paths.get(inputDirPath), 1)) { List<Path> targetFiles = pathStream.filter(Files::isRegularFile).toList(); for (Path file : targetFiles) { try (BufferedReader br = Files.newBufferedReader(file)) { String currentLine; boolean isFirstLine = true; while ((currentLine = br.readLine()) != null) { if (isFirstLine) { // 读取第一个文件的表头作为全局表头 if (globalHeader == null) { globalHeader = currentLine.split(","); } isFirstLine = false; continue; } String[] lineParts = currentLine.split(","); if (lineParts.length < 3) continue; try { // 解析时间戳为毫秒数值,复用原有两文件合并的比较逻辑 Timestamp ts = Timestamp.valueOf(lineParts[0].trim()); sortableData.add(new String[]{String.valueOf(ts.getTime()), currentLine}); } catch (IllegalArgumentException e) { // 自动跳过格式异常的无效行 } } } } } // 按时间戳毫秒值全局排序,和原有两文件归并的比较规则完全一致 sortableData.sort(Comparator.comparingLong(item -> Long.parseLong(item[0]))); // 写出合并文件 try (BufferedWriter bw = Files.newBufferedWriter(Paths.get(outputPath))) { if (globalHeader != null) { bw.write(String.join(",", globalHeader)); bw.newLine(); } for (String[] row : sortableData) { bw.write(row[1]); bw.newLine(); } } } // 调用示例 public static void main(String[] args) throws IOException { mergeAllFiles("./input_folder_path", "./merged_result.csv"); } }
拓展适配场景
- 当待合并文件总大小超出内存承载上限时,可将全量内存排序替换为外部排序逻辑:先把每个单文件按时间戳排序落盘,再基于原有两文件归并能力做多路归并,不需要改动核心比较和合并逻辑
- 合并时可根据需要增加文件过滤规则,避免把无关格式的文件纳入处理范围
内容的提问来源于stack exchange,提问作者user15232574
相关产品推荐
相关产品推荐

