如何按文件名前缀将PDF文件存入数组并排序以实现批量合并?
PDF按前缀分组合并的C#实现方案
原代码存在的核心问题
Directory.GetFiles参数逻辑错误:"*.pdf".Split('_')[0]仅会拆分字符串"*.pdf",得到的过滤条件完全无法实现按前缀筛选的需求- 缺失按前缀分组的核心逻辑,直接合并所有文件不符合业务要求
- 未对每组内的文件进行排序处理
- 命令行参数未处理路径空格问题,可能导致pdftk执行失败
修正后的完整代码
using System; using System.Diagnostics; using System.IO; using System.Linq; using bin_vMergePdfNeu.Properties; namespace bin_vMergePdfNeu // 修正命名空间,避免与系统命名空间冲突 { class Program { static void Main(string[] args) { Console.Title = "bin_vMergePDF"; // 读取配置中的输入输出目录 string inputDir = Settings.Default.AlternativeInputDir; string outputDir = Settings.Default.AlternativeOutputDir; // 确保输出目录存在,不存在则创建 if (!Directory.Exists(outputDir)) { Directory.CreateDirectory(outputDir); } try { // 1. 获取目录下所有PDF文件 var allPdfFiles = Directory.GetFiles(inputDir, "*.pdf", SearchOption.TopDirectoryOnly); // 2. 按文件名前缀(第一个下划线前的部分)分组 var groupedFiles = allPdfFiles.GroupBy(filePath => { string fileName = Path.GetFileName(filePath); int underscoreIndex = fileName.IndexOf('_'); // 处理无下划线的文件,直接用完整文件名作为分组键 return underscoreIndex > 0 ? fileName.Substring(0, underscoreIndex) : fileName; }); // 3. 遍历每个分组,执行合并操作 foreach (var group in groupedFiles) { // 对组内文件按文件名排序(可根据需求调整排序规则) var sortedFiles = group.OrderBy(filePath => Path.GetFileName(filePath)).ToList(); // 生成合并后的输出文件名 string outputFileName = $"{group.Key}_merged.pdf"; string outputPath = Path.Combine(outputDir, outputFileName); // 构建pdftk命令参数:用双引号包裹路径,避免空格导致的识别错误 string fileArgs = string.Join(" ", sortedFiles.Select(f => $"\"{f}\"")); string cmdArgs = $"{fileArgs} cat output \"{outputPath}\""; // 启动pdftk进程执行合并 using (Process p = new Process()) { p.StartInfo.WorkingDirectory = Environment.CurrentDirectory; p.StartInfo.FileName = "pdftk.exe"; p.StartInfo.Arguments = cmdArgs; p.StartInfo.UseShellExecute = false; p.StartInfo.RedirectStandardOutput = true; p.StartInfo.RedirectStandardError = true; p.Start(); // 读取执行信息 string errorMsg = p.StandardError.ReadToEnd(); string outputMsg = p.StandardOutput.ReadToEnd(); p.WaitForExit(); // 输出执行结果 if (!string.IsNullOrEmpty(errorMsg)) { Console.WriteLine($"合并前缀【{group.Key}】时出错:{errorMsg}"); } else { Console.WriteLine($"前缀【{group.Key}】合并完成,输出文件:{outputPath}"); } } } } catch (Exception ex) { Console.WriteLine($"程序执行异常:{ex.Message}"); } Console.WriteLine("\n所有分组处理完成,按任意键退出..."); Console.ReadKey(); } } }
关键逻辑说明
- 分组逻辑:通过
GroupBy提取每个文件名第一个下划线前的内容作为分组键,确保相同前缀的文件被归为一组 - 排序逻辑:默认按文件名排序,若需按其他规则(比如文件名第三段的数字),可修改排序条件,示例:
var sortedFiles = group.OrderBy(filePath => { string fileName = Path.GetFileName(filePath); string[] parts = fileName.Split('_'); return parts.Length >=3 ? parts[2] : fileName; }).ToList(); - 路径兼容:所有文件路径用双引号包裹,解决路径含空格时pdftk无法识别的问题
- 异常防护:添加全局异常捕获,避免程序意外崩溃,同时输出详细错误信息便于排查
内容的提问来源于stack exchange,提问作者aljoscha
相关产品推荐
相关产品推荐

