
本教程详细介绍了如何在Java应用程序中使用Apachee PDFBox库从PDF文档中提取文本并根据搜索结果复制或移动文件。本文将澄清为什么PDF不能直接作为普通文本文件处理提供完整的代码示例包括PDF文本提取、关键字搜索和文件系统操作并分享重要的预防措施和最佳实践以帮助开发人员构建稳定可靠的PDF处理功能。了解PDF文件的特性和传统文本阅读的局限性PDFPortable Document Format文件是一种复杂的二进制格式旨在保留文档的视觉外观无论在哪种设备或操作系统上。与简单的文本文件不同PDF内部存储的指令集不是纯文本字符流而是包含字体、图像、矢量图形、页面布局等元素。因此试着使用标准I/O类别如Java的Filereader或bufferedreader直接读取PDF文件并希望通过Readline()或contains()搜索文本无效。这些方法将PDF的二进制内容解释为字符导致读取无序代码或无法识别的数据无法正确执行文本搜索也可能导致后续处理中的异常或“文件内容错误”。为了正确地从PDF中提取可读文本我们需要一个特殊的库来分析其内部结构。引入Apache PDFBox库Apache PDFBox是专门用于处理PDF文档的开源Java库。它提供了创建、修改、提取文本、渲染和打印PDF文件等丰富的功能。PDFBox是业界广泛推荐和使用的解决方案以满足从PDF中提取文本的需求。依赖PDFBox来添加PDFBox在开始之前您需要在您的项目中添加Apache PDFBox的依赖。如果使用Maven可以在pom.在xml文件中添加以下内容dependency groupIdorg.apache.pdfbox/groupId artifactIdpdfbox/artifactId version2.0.29/version !-- 请使用最新的稳定版本 -- /dependency如果使用Gradle可以使用build.添加到gradle文件中implementation org.apache.pdfbox:pdfbox:2.0.29 // 请使用最新的稳定版本从PDF中提取文本PDFBox从PDF文件中提取文本的基本步骤如下加载PDF文档 通过PDDocumenten.load(File file)方法加载指定的PDF文件。PDFTextstripper实例化 PDFTextstriper类负责从PDF文档中提取文本内容。提取文本 pdfstripper调用pdfripper.getText(PDDocument document)该方法获取整个文档的文本内容并返回String。关闭文档 提取完成后必须调用document.close()释放资源的方法。以下是提取PDF文本的示例代码import java.io.File; import java.io.IOException; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.text.PDFTextStripper; public class PdfTextExtractor { public String extractText(String filePath) throws IOException { File file new File(filePath); PDDocument document null; try { document PDDocument.load(file); PDFTextStripper pdfStripper new PDFTextStripper(); return pdfStripper.getText(document); } finally { if (document ! null) { document.close(); } } } public static void main(String[] args) { String pdfPath D://Sample.pdf; // 替换您的PDF文件路径 PdfTextExtractor extractor new PdfTextExtractor(); try { String text extractor.extractText(pdfPath); System.out.println(提取的PDF文本内容 text.substring(0, Math.min(text.length(), 500)) ...); // 打印前500字符 } catch (IOException e) { System.err.println(从PDF提取文本时出错 e.getMessage()); e.printStackTrace(); } } }实现文本搜索逻辑一旦我们成功地从PDF中提取了完整的文本内容一个String对象我们就可以像处理任何其他字符串一样搜索它。Java的String类别提供了一种方法来检查一个字符串是否包含另一个子字符串。为了实现不区分大小写的搜索文本和搜索词可以首先转换为小写或大写。public boolean searchWordInPdf(String pdfText, String searchWord) { if (pdfText null || searchWord null || searchWord.isEmpty()) { return false; } // 为了不区分大小写将两者转化为小写进行比较 return pdfText.toLowerCase().contains(searchWord.toLowerCase()); }文件操作复制和移动在确认PDF中包含特定关键字后下一步通常是复制或移动PDF文件到另一个目录。Java 引入的NIO.2java.nio.file包)提供强大高效的文件系统操作API。复制文件 使用Files.copy(Path source, Path target, CopyOption... options)。移动文件 使用Files.move(Path source, Path target, CopyOption... options)。这些方法允许您指定复制或移动的选项例如StandardCopyOption.REPLACE_EXISTING(如果目标文件已存在则覆盖)或StandardCopyoption.ATOMIC_MOVE(试着执行原子移动)。import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; public class FileOperations { public void copyFile(String sourcePath, String targetDirectory, String newFileName) throws IOException { Path source Paths.get(sourcePath); Path targetDir Paths.get(targetDirectory); if (!Files.exists(targetDir)) { Files.createDirectories(targetDir); // 如果目标目录不存在则创建 } Path target targetDir.resolve(newFileName); // 构建目标文件路径 Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING); System.out.println(文件 source.getFileName() 已成功复制 target 。); } public void moveFile(String sourcePath, String targetDirectory, String newFileName) throws IOException { Path source Paths.get(sourcePath); Path targetDir Paths.get(targetDirectory); if (!Files.exists(targetDir)) { Files.createDirectories(targetDir); // 如果目标目录不存在则创建 } Path target targetDir.resolve(newFileName); // 构建目标文件路径 Files.move(source, target, StandardCopyOption.REPLACE_EXISTING); System.out.println(文件 source.getFileName() 移动成功 target 。); } }完整示例代码PDF文本搜索和文件管理现在我们将上述所有组件集成到一个完整的Java应用程序中从用户输入搜索词然后在指定的PDF中搜索并根据结果执行文件操作。import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import java.util.Scanner; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.text.PDFTextStripper; public class PdfSearchAndMove { private static final String PDF_FILE_PATH C:\Users\user012Desktop\Evalution.pdf; // PDF文件路径需要搜索 private static final String TARGET_DIR_PATH C:\Users\user012Desktop\Search; // 目标目录路径 /** * 从PDF文件中提取所有文本内容。 * param filePath PDF文件路径 * return 提取的文本内容 * throws IOException 如果文件不存在或处理PDF时出现错误 */ public String extractTextFromPdf(String filePath) throws IOException { File file new File(filePath); if (! * param filePath PDF文件路径 * return 提取的文本内容 * throws IOException 如果文件不存在或处理PDF时出现错误 */ public String extractTextFromPdf(String filePath) throws IOException { File file new File(filePath); if (!file.exists() || !file.isFile()) { throw new IOException(PDF文件不存在或不是有效文件 filePath); } PDDocument document null; try { document PDDocument.load(file); PDFTextStripper pdfStripper new PDFTextStripper(); return pdfStripper.getText(document); } finally { if (document ! null) { document.close(); } } } /** * 在给定的文本内容中搜索指定的关键字。 * param pdfText 从PDF中提取的文本内容 * param searchWord 要搜索的关键词 * return 如果找到关键字返回true否则返回false */ public boolean containsWord(String pdfText, String searchWord) { if (pdfText null || searchWord null || searchWord.isEmpty()) { return false; } // 大小写搜索没有区别 return pdfText.toLowerCase().contains(searchWord.toLowerCase()); } /** * 将文件从源路径复制到目标目录。 * param sourceFilePath 源文件路径 * param targetDirectory 目标目录路径 * param newFileName 新名称的目标文件 * throws IOException 若复制操作失败 */ public void copyPdfFile(String sourceFilePath, String targetDirectory, String newFileName) throws IOException { Path source Paths.get(sourceFilePath); Path targetDir Paths.get(targetDirectory); // 确保目标目录的存在 if (!Files.exists(targetDir)) { Files.createDirectories(targetDir); } Path target targetDir.resolve(newFileName); // 复制文件如果目标文件存在则更换 Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING); System.out.println(文件 source.getFileName() 已成功复制 target 。); } public static void main(String[] args) { Scanner scanner new Scanner(System.in); PdfSearchAndMove app new PdfSearchAndMove(); System.out.println(请输入您想要搜索的单词 (输入 Exit 退出):); while (scanner.hasNextLine()) { String searchWord scanner.nextLine().trim(); if (Exit.equalsIgnoreCase(searchWord)) { System.out.println(程序退出。); break; } if (searchWord.isEmpty()) { System.out.println(搜索词不能为空请重新输入。); continue; } try { // 1. 从PDF中提取文本 String pdfContent app.extractTextFromPdf(PDF_FILE_PATH); // 2. 搜索关键词 if (app.containsWord(pdfContent, searchWord)) { System.out.println(是的 searchWord 在文件中。); // 3. 如果找到则复制文件 // 假设复制后的文件名称为原文件名_searched后缀 String originalFileName Paths.get(PDF_FILE_PATH).getFileName().toString(); String newFileName originalFileName.replaceFirst((\.pdf)$, _searched$1); app.copyPdfFile(PDF_FILE_PATH, TARGET_DIR_PATH, newFileName); } else { System.out.println(不 searchWord 不在文件中。); } } catch (IOException e) { System.err.println(处理文件时出现错误 e.getMessage()); // 打印完整的堆栈跟踪以便调试 e.printStackTrace(); } catch (Exception e) { System.err.println(未知错误发生 e.getMessage()); e.printStackTrace(); } System.out.println( 请输入您想要搜索的下一个单词 (输入 Exit 退出):); } scanner.close(); } }注意事项和最佳实践资源管理 使用PDDocument后始终确保调用document.close()方法。这对于释放文件句柄和内存资源非常重要尤其是在处理大量PDF文件时。使用try-finally块或Java 7的try-with-resources语句能有效管理资源。异常处理 IOException可以扔出文件I/O和PDF分析操作。一定要捕获并妥善处理这些异常如打印错误信息或记录日志以提高程序的强度。性能考虑 对于非常大的PDF文件pdfStripper.getText()可能会消耗更多的内存和时间。如果只需要搜索特定页面或对性能有严格要求可以考虑优化PDFBox的使用比如分批处理页面。文件路径 在Windows系统中反斜杠通常用于文件路径。在Java代码中建议使用正斜杠/或双反斜杠\来表示路径或使用Paths.get()方法它能更好地处理不同操作系统的路径分隔符。命名目标文件 在复制或移动文件时应仔细考虑目标文件的命名策略以避免覆盖重要文件。例如我们添加了_searched后缀。错误信息 在原始问题中提到“原始问题中提到”the pdf file showing something wrong这通常意味着文件内容被破坏或无法识别。使用正确的库(如PDFBox)来处理PDF可以避免此类问题。用户体验 在实际应用中可以添加进度指示器、更详细的错误提示等以提高用户体验。通过遵循本教程的指导和最佳实践您可以在Java应用程序中可靠地实现基于搜索结果的PDF文本搜索和文件管理功能。