Я использую PdfBox в Java для извлечения текста из файлов PDF. Некоторые из представленных входных файлов недействительны, и PDFTextStripper останавливается на этих файлах. Есть ли чистый способ проверить, действительно ли предоставленный файл действительно является PDF?Как определить, является ли файл PDF-файлом?
ответ
вы можете узнать тип mime файла (или массив байтов), чтобы вы не полагались на расширение. Я делаю это с MimeExtractor апертуры в (http://aperture.sourceforge.net/) или я видел несколько дней назад библиотеку только для этого (http://sourceforge.net/projects/mime-util)
я использую отверстие для извлечения текста из различных файлов, а не только PDF, но нужно настроить думает PDFs например (диафрагма использует pdfbox, но я добавил еще одну библиотеку в качестве запасного варианта, когда pdfbox терпит неудачу)
спасибо, я попробую – 2009-06-07 15:36:44
О, я забыл упомянуть, что теперь есть проект apache для извлечения текста, http://lucene.apache.org/tika/, если вы предпочитаете его апертуру – Persimmonium
Не знаете, как это сделать решает исходный вопрос, используя PDFBox. – cherouvim
Pdf файлы начинаются «% PDF» (открыть один в TextPad или аналогичный и взглянуть)
какой-либо причине вы не можете просто прочитать файл с StringReader и проверить это?
Я пробовал это, и кажется, что в файлах PDF могут использоваться различные кодировки, и иногда чтение текста не соответствует% PDF для действительных и читаемых PDF-файлов. – 2009-06-02 21:19:31
Не все файлы, начинающиеся с% PDF, являются действительными файлами PDF. –
Вот что я использую в моих тестах NUnit, которые должны подтвердить против нескольких версий PDF, полученных с помощью Crystal Reports:
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-файлом - проблема EOL, проявленная только в Adobe Reader, а не в Foxit/GoogleApps/Sumatra. –
Это на Java? Также он не будет обнаруживать зашифрованные PDF-файлы. Поскольку OP хочет извлечь информацию, вам это тоже нужно. – cherouvim
Спасибо! Я очень признателен, что этот ответ является агностиком библиотеки. Это спасло мне кучу времени =) – Spina
Поскольку вы используете PDFBox, вы можете просто:
PDDocument.load(file);
Это будет терпеть неудачу с Exception, если PDF поврежден и т.д.
Если это удастся вы также можете проверить, если PDF зашифрован с помощью .isEncrypted()
Из того, что я видел, это неправда. Я могу использовать PDDocument.load (поток) для загрузки поврежденного PDF-файла. Я получаю сообщение об ошибке при попытке сохранить PDF после изменения его прав доступа. – MonkeyWrench
Использование Исключения для потока приложений - это плохая практика. –
@BenTurner: Вы правы, и я с вами на этом. Однако API не дает нам возможности проверить действительность файла. – cherouvim
Вы должны попробовать это ... .
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-», а просто содержит его? Почему проблема чтения всего файла? Что делать, если я проверяю zip-файл на 2 ГБ? – boumbh
для больших файлов, файлов размером 10 + МБ и неправильных расширений (например, mp3File.pdf), потребуется много времени (например, 5 и более секунд). – shanraisshan
Существует очень удобная и простая библиотека для тестирования содержания 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"));
}
}
Здесь адаптированный Java версия кода NinjaCross в.
/**
* 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()));
}
Если вы придумали какие-либо неудовлетворительные модульные тесты, пожалуйста, дайте мне знать.
Возможно, я опоздал, чтобы ответить. Но вы должны взглянуть на Тику. Он использует PDFBox Parser внутренне для анализа PDF в
Вам просто нужно импортировать ТИКА-приложение-последний * .jar
public String parseToStringExample() throws IOException, SAXException, TikaException
{
Tika tika = new Tika();
try (InputStream stream = ParsingExample.class.getResourceAsStream("test.pdf")) {
return tika.parseToString(stream); // This should return you the pdf's text
}
}
Было бы гораздо чище решение. Вы можете обратиться сюда для получения более подробной информации о Tika Использование: https://tika.apache.org/1.12/api/
Я использовал некоторые предложения, которые я нашел здесь, и на других сайтах/сообщениях для определения того, был ли pdf действителен или нет. Я намеренно исказил файл PDF, и, к сожалению, многие из этих решений не обнаружили, что файл поврежден.
В конце концов, после того, как мастерить вокруг с различными методами в API, я попытался это:
PDDocument.load(file).getPage(0).getContents().toString();
Это не сгенерирует исключение, но он сделал вывод этого:
WARN [COSParser:1154] The end of the stream doesn't point to the correct offset, using workaround to read the stream, stream start position: 171, length: 1145844, expected end position: 1146015
Лично я хотел, чтобы исключение было выброшено, если файл был поврежден, поэтому я мог справиться с этим сам, но оказалось, что API, который я реализовал, уже обрабатывал их по-своему.
Чтобы обойти это, я решил попробовать разбор файлов, используя класс, который дал теплый оператор (COSParser). Я обнаружил, что существует подкласс под названием PDFParser, который унаследовал метод «setLenient», который был ключом (https://pdfbox.apache.org/docs/2.0.4/javadocs/org/apache/pdfbox/pdfparser/COSParser.html).
Я тогда реализован следующим образом:
RandomAccessFile accessFile = new RandomAccessFile(file, "r");
PDFParser parser = new PDFParser(accessFile);
parser.setLenient(false);
parser.parse();
Это бросил исключение для моего поврежденного файла, как я хотел. Надеюсь, это поможет кому-то!
Ответ Roger Keays неверен! поскольку не все файлы PDF в версии 1.3 и не все завершены EOL. Ответ ниже работ для всех не поврежденных файлов PDF:
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;
}
«%% EOF» должно быть единственным содержимым в последней строке PDF. Таким образом, файлы с пробелом после '%% EOF' строго говоря недействительны. После него может быть только разделитель строк, то есть один CR, одна LF или пара CR LF. – mkl
В общем, мы можем, как это, любая PDF версия собирается закончить с %% EOF, чтобы мы могли проверить, как сильфон.
public static boolean is_pdf(byte[] data) {
String s = new String(data);
String d = s.substring(data.length - 7, data.length - 1);
if (data != null && data.length > 4 &&
data[0] == 0x25 && // %
data[1] == 0x50 && // P
data[2] == 0x44 && // D
data[3] == 0x46 && // F
data[4] == 0x2D) { // -
if(d.contains("%%EOF")){
return true;
}
}
return false;
}
- 1. Определить, является ли файл значком
- 2. определить, является ли файл изображением
- 3. Как определить, является ли файл ссылкой?
- 4. Как определить, является ли файл zip-файлом?
- 5. Как определить, является ли файл IBM1047 кодируются
- 6. определить, является ли файл на сервере существует
- 7. Определить, является ли файл PDF в perl?
- 8. Определить, является ли файл * доступен для записи
- 9. Определить, является ли файл двоичным или текстовым
- 10. объект является Как определить, является ли последовательность
- 11. Как определить данный файл является файлом класса?
- 12. Определить, если файл является доступным
- 13. регулярное выражение, чтобы определить, является ли файл SQL-файл
- 14. Как определить, пуст ли файл?
- 15. Как определить, является ли файл значком в PHP?
- 16. Как определить, является ли файл именованным каналом в java
- 17. Как определить, является ли файл текстом с использованием PHP?
- 18. Как определить, является ли файл изображением в perl
- 19. Как определить, является ли файл дампа аварийным сбой
- 20. Как определить, является ли файл mysqldump с bzipped пустым/нулевым?
- 21. Как определить, является ли файл графическим, видео или аудиофайлом
- 22. Как определить, является ли файл потомком данного каталога?
- 23. Как определить, является ли открытый файл гнездом или трубой?
- 24. Как определить, является ли файл C компилятором gcc?
- 25. Как определить, является ли файл EXE или DLL?
- 26. Как определить, является ли файл файлом изображения в .NET?
- 27. Как определить, является ли файл PDF или TIFF?
- 28. Как определить, действительно ли предоставленный файл является кустом реестра
- 29. Как определить, является ли данный файл файлом xml valide
- 30. Как определить, является ли файл неизвестным типом файла C#
Отличный вопрос! Мое королевство для высококачественного непубличного PDF-валидатора. –