Как я могу определить, является ли файл файлом PDF? - PullRequest
30 голосов
/ 03 июня 2009

Я использую PdfBox в Java для извлечения текста из файлов PDF. Некоторые из предоставленных входных файлов недействительны, и PDFTextStripper останавливается на этих файлах. Есть ли простой способ проверить, является ли предоставленный файл действительно действительным PDF?

Ответы [ 12 ]

0 голосов
/ 07 марта 2019

Вот метод, который проверяет наличие %%EOF с дополнительными проверками на наличие пробелов. Вы можете передать либо File, либо byte[] объект. В некоторых версиях PDF меньше ограничений на символы пробела.

public boolean isPdf(byte[] data) {
    if (data == null || data.length < 5) return false;
    // %PDF-
    if (data[0] == 0x25 && data[1] == 0x50 && data[2] == 0x44 && data[3] == 0x46 && data[4] == 0x2D) {
        int offset = data.length - 8, count = 0; // check last 8 bytes for %%EOF with optional white-space
        boolean hasSpace = false, hasCr = false, hasLf = false;
        while (offset < data.length) {
            if (count == 0 && data[offset] == 0x25) count++; // %
            if (count == 1 && data[offset] == 0x25) count++; // %
            if (count == 2 && data[offset] == 0x45) count++; // E
            if (count == 3 && data[offset] == 0x4F) count++; // O
            if (count == 4 && data[offset] == 0x46) count++; // F
            // Optional flags for meta info
            if (count == 5 && data[offset] == 0x20) hasSpace = true; // SPACE
            if (count == 5 && data[offset] == 0x0D) hasCr    = true; // CR
            if (count == 5 && data[offset] == 0x0A) hasLf    = true; // LF / EOL
            offset++;
        }

        if (count == 5) {
            String version = data.length > 13 ? String.format("%s%s%s", (char) data[5], (char) data[6], (char) data[7]) : "?";
            System.out.printf("Version : %s | Space : %b | CR : %b | LF : %b%n", version, hasSpace, hasCr, hasLf);
            return true;
        }
    }

    return false;
}
public boolean isPdf(File file) throws IOException {
    return isPdf(file, false);
}
// With version: 16 bytes, without version: 13 bytes.
public boolean isPdf(File file, boolean includeVersion) throws IOException {
    if (file == null) return false;
    int offsetStart = includeVersion ? 8 : 5, offsetEnd = 8;
    byte[] bytes = new byte[offsetStart + offsetEnd];
    InputStream is = new FileInputStream(file);
    try {
        is.read(bytes, 0, offsetStart); // %PDF-
        is.skip(file.length() - bytes.length); // Skip bytes
        is.read(bytes, offsetStart, offsetEnd); // %%EOF,SP?,CR?,LF?
    } finally {
        is.close();
    }
    return isPdf(bytes);
}
0 голосов
/ 16 августа 2015

Существует очень удобная и простая библиотека для тестирования содержимого PDF: https://github.com/codeborne/pdf-test

API очень прост:

import com.codeborne.pdftest.PDF;
import static com.codeborne.pdftest.PDF.*;
import static org.junit.Assert.assertThat;

public class PDFContainsTextTest {
  @Test
  public void canAssertThatPdfContainsText() {
    PDF pdf = new PDF(new File("src/test/resources/50quickideas.pdf"));
    assertThat(pdf, containsText("50 Quick Ideas to Improve your User Stories"));
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...