我在Java中使用PdfBox从PDF文件中提取文本.提供的某些输入文件无效,PDFTextStripper会暂停这些文件.是否有一种干净的方法来检查提供的文件是否确实是有效的PDF?
以下是我在NUnit测试中使用的内容,它必须针对使用Crystal Reports生成的多个PDF版本进行验证:
public static void CheckIsPDF(byte[] data) { Assert.IsNotNull(data); Assert.Greater(data.Length,4); // header Assert.AreEqual(data[0],0x25); // % Assert.AreEqual(data[1],0x50); // P Assert.AreEqual(data[2],0x44); // D Assert.AreEqual(data[3],0x46); // F Assert.AreEqual(data[4],0x2D); // - if(data[5]==0x31 && data[6]==0x2E && data[7]==0x33) // version is 1.3 ? { // file terminator Assert.AreEqual(data[data.Length-7],0x25); // % Assert.AreEqual(data[data.Length-6],0x25); // % Assert.AreEqual(data[data.Length-5],0x45); // E Assert.AreEqual(data[data.Length-4],0x4F); // O Assert.AreEqual(data[data.Length-3],0x46); // F Assert.AreEqual(data[data.Length-2],0x20); // SPACE Assert.AreEqual(data[data.Length-1],0x0A); // EOL return; } if(data[5]==0x31 && data[6]==0x2E && data[7]==0x34) // version is 1.4 ? { // file terminator Assert.AreEqual(data[data.Length-6],0x25); // % Assert.AreEqual(data[data.Length-5],0x25); // % Assert.AreEqual(data[data.Length-4],0x45); // E Assert.AreEqual(data[data.Length-3],0x4F); // O Assert.AreEqual(data[data.Length-2],0x46); // F Assert.AreEqual(data[data.Length-1],0x0A); // EOL return; } Assert.Fail("Unsupported file format"); }
你可以找到一个文件(或字节数组)的mime类型,所以你不要愚蠢地依赖扩展.我是用光学的MimeExtractor(http://aperture.sourceforge.net/)做的,或者我前几天看到了一个图书馆(http://sourceforge.net/projects/mime-util)
我使用光圈从各种文件中提取文本,不仅仅是pdf,而且必须调整为pdfs思考(光圈使用pdfbox,但我在pdfbox失败时添加了另一个库作为后备)
由于您使用PDFBox,您可以简单地执行:
PDDocument.load(file);
如果PDF损坏等,它将以异常失败.
如果成功,您还可以检查PDF是否使用加密 .isEncrypted()
这里是NinjaCross代码的改编Java版本.
/** * Test if the data in the given byte array represents a PDF file. */ public static boolean is_pdf(byte[] data) { if (data != null && data.length > 4 && data[0] == 0x25 && // % data[1] == 0x50 && // P data[2] == 0x44 && // D data[3] == 0x46 && // F data[4] == 0x2D) { // - // version 1.3 file terminator if (data[5] == 0x31 && data[6] == 0x2E && data[7] == 0x33 && data[data.length - 7] == 0x25 && // % data[data.length - 6] == 0x25 && // % data[data.length - 5] == 0x45 && // E data[data.length - 4] == 0x4F && // O data[data.length - 3] == 0x46 && // F data[data.length - 2] == 0x20 && // SPACE data[data.length - 1] == 0x0A) { // EOL return true; } // version 1.3 file terminator if (data[5] == 0x31 && data[6] == 0x2E && data[7] == 0x34 && data[data.length - 6] == 0x25 && // % data[data.length - 5] == 0x25 && // % data[data.length - 4] == 0x45 && // E data[data.length - 3] == 0x4F && // O data[data.length - 2] == 0x46 && // F data[data.length - 1] == 0x0A) { // EOL return true; } } return false; }
还有一些简单的单元测试:
@Test public void test_valid_pdf_1_3_data_is_pdf() { assertTrue(is_pdf("%PDF-1.3 CONTENT %%EOF \n".getBytes())); } @Test public void test_valid_pdf_1_4_data_is_pdf() { assertTrue(is_pdf("%PDF-1.4 CONTENT %%EOF\n".getBytes())); } @Test public void test_invalid_data_is_not_pdf() { assertFalse(is_pdf("Hello World".getBytes())); }
如果你想出任何失败的单元测试,请告诉我.
你必须尝试这个....
public boolean isPDF(File file){ file = new File("Demo.pdf"); Scanner input = new Scanner(new FileReader(file)); while (input.hasNextLine()) { final String checkline = input.nextLine(); if(checkline.contains("%PDF-")) { // a match! return true; } } return false; }