当前位置:  开发笔记 > 编程语言 > 正文

如何确定文件是否为PDF文件?

如何解决《如何确定文件是否为PDF文件?》经验,为你挑选了5个好方法。

我在Java中使用PdfBox从PDF文件中提取文本.提供的某些输入文件无效,PDFTextStripper会暂停这些文件.是否有一种干净的方法来检查提供的文件是否确实是有效的PDF?



1> NinjaCross..:

以下是我在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");
    }


谢谢,这只是帮助我弄清楚我生成的PDF出了什么问题 - 只在Adobe Reader中显示EOL问题,而不是Foxit/GoogleApps/Sumatra.
谢谢!我真的很感激这个答案是库不可知的.它为我节省了一大堆时间=)

2> Persimmonium..:

你可以找到一个文件(或字节数组)的mime类型,所以你不要愚蠢地依赖扩展.我是用光学的MimeExtractor(http://aperture.sourceforge.net/)做的,或者我前几天看到了一个图书馆(http://sourceforge.net/projects/mime-util)

我使用光圈从各种文件中提取文本,不仅仅是pdf,而且必须调整为pdfs思考(光圈使用pdfbox,但我在pdfbox失败时添加了另一个库作为后备)


我在问题的标题中看到"使用Apache的PdfBox".如果使用PDFBox解决问题并不比引入额外的依赖更好吗?

3> cherouvim..:

由于您使用PDFBox,您可以简单地执行:

PDDocument.load(file);

如果PDF损坏等,它将以异常失败.

如果成功,您还可以检查PDF是否使用加密 .isEncrypted()


从我所看到的,那不是真的.我可以使用PDDocument.load(流)加载损坏的PDF.尝试在修改PDF权限后保存PDF时,我只会收到错误.

4> Roger Keays..:

这里是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()));
}

如果你想出任何失败的单元测试,请告诉我.



5> Sheel..:

你必须尝试这个....

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;
}


这个答案给我带来了麻烦......是否有不以"%PDF-"开头但只包含它的PDF?为什么读取整个文件的麻烦?如果我检查2 GB的zip文件怎么办?
推荐阅读
Life一切安好
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有