Получить точное строковое задание в PDF

Я попытался прочитать stream и надеялся получить для каждой строки точное положение (координаты)

int size = reader.getXrefSize(); for (int i = 0; i < size; ++i) { PdfObject pdfObject = reader.getPdfObject(i); if ((pdfObject == null) || !pdfObject.isStream()) continue; PdfStream stream = (PdfStream) pdfObject; PdfObject obj = stream.get(PdfName.FILTER); if ((obj != null) && obj.toString().equals(PdfName.FLATEDECODE.toString())) { byte[] codedText = PdfReader.getStreamBytesRaw((PRStream) stream); byte[] text = PdfReader.FlateDecode(codedText); FileOutputStream o = new FileOutputStream(new File("/home..../Text" + i + ".txt")); o.write(text); o.flush(); o.close(); } } 

Я действительно получил позицию, подобную

 ...... BT 70.9 800.9 Td /F1 14 Tf  Tj 10.1 0 Td  Tj 9.3 0 Td  Tj 3.9 0 Td  Tj 10.1 0 Td  Tj 18.7 0 Td  Tj 21 0 Td  Tj 24.9 0 Td  Tj 10.1 0 Td  Tj 28.8 0 Td  Tj 3.8 0 Td  Tj 8.6 0 Td  Tj 29.5 0 Td  Tj 16.4 0 Td  Tj 7.8 0 Td  Tj 12.4 0 Td  Tj 7.8 0 Td  Tj 3.9 0 Td  Tj 7.8 0 Td  Tj 7.8 0 Td  Tj 3.9 0 Td  Tj 10.8 0 Td  Tj 7.8 0 Td  Tj 10.9 0 Td  Tj ET ..... 

Но я не знаю, какая строка подходит для какой позиции. С другой стороны, в Itext я мог просто получить простой текст с

 PdfReader reader = new PdfReader(new FileInputStream("/home/....xxx.pdf")); PdfTextExtractor extract = new PdfTextExtractor(reader); 

но, конечно, без какой-либо позиции …

Итак, как я могу получить точную позицию для каждого текста (строка, char, …)?

Как уже указывали в своих ответах плинтус и Дэвид ван Дриссе, выведение текста из файла PDF является нетривиальным. К счастью, classы в пакете парсеров iText делают большую часть тяжелой работы для вас. Вы уже нашли хотя бы один class из этого пакета PdfTextExtractor, но этот class по сути является удобной утилитой для использования функциональности парсера iText, если вас интересует только простой текст страницы. В вашем случае вы должны более внимательно изучать classы в этом пакете.

Отправной точкой для получения информации о теме извлечения текста с помощью iText является раздел 15.3 Разбор PDF-файлов iText в действии – второе издание , особенно метод extractText образца ParsingHelloWorld.java :

 public void extractText(String src, String dest) throws IOException { PrintWriter out = new PrintWriter(new FileOutputStream(dest)); PdfReader reader = new PdfReader(src); RenderListener listener = new MyTextRenderListener(out); PdfContentStreamProcessor processor = new PdfContentStreamProcessor(listener); PdfDictionary pageDic = reader.getPageN(1); PdfDictionary resourcesDic = pageDic.getAsDict(PdfName.RESOURCES); processor.processContent(ContentByteUtils.getContentBytesForPage(reader, 1), resourcesDic); out.flush(); out.close(); } 

который использует реализацию RenderListener MyTextRenderListener.java :

 public class MyTextRenderListener implements RenderListener { [...] /** * @see RenderListener#renderText(TextRenderInfo) */ public void renderText(TextRenderInfo renderInfo) { out.print("<"); out.print(renderInfo.getText()); out.print(">"); } } 

Хотя эта реализация RenderListener просто выводит текст, объект TextRenderInfo, который он проверяет, предлагает больше информации:

 public LineSegment getBaseline(); // the baseline for the text (ie the line that the text 'sits' on) public LineSegment getAscentLine(); // the ascentline for the text (ie the line that represents the topmost extent that a string of the current font could have) public LineSegment getDescentLine(); // the descentline for the text (ie the line that represents the bottom most extent that a string of the current font could have) public float getRise() ; // the rise which represents how far above the nominal baseline the text should be rendered public String getText(); // the text to render public int getTextRenderMode(); // the text render mode public DocumentFont getFont(); // the font public float getSingleSpaceWidth(); // the width, in user space units, of a single space character in the current font public List getCharacterRenderInfos(); // details useful if a listener needs access to the position of each individual glyph in the text render operation 

Таким образом, если ваш RenderListener в дополнение к проверке текста с getText() также рассматривает getBaseline() или даже getAscentLine() и getDescentLine(). у вас есть все координаты, которые вам, скорее всего, понадобятся.

PS: Существует class оболочки для кода в ParsingHelloWorld.extractText() , PdfReaderContentParser , который позволяет вам просто написать следующее PdfReader reader, int page, и RenderListener renderListener:

 PdfReaderContentParser parser = new PdfReaderContentParser(reader); parser.processContent(page, renderListener); 

Если вы пытаетесь выполнить извлечение текста, вы должны знать, что это определенно нетривиальный процесс. Вам, как минимум, придется внедрить машину RPN для запуска кода и накопления преобразований и выполнения всех текстовых операторов. Вам нужно будет интерпретировать метрики шрифтов из текущего набора ресурсов страницы, и вам, вероятно, потребуется понять кодировку текста.

Когда я работал над Acrobat 1.0, я отвечал за команду «Найти …», которая включала вашу проблему в качестве подмножества. С более богатым набором инструментов и большим опытом, потребовалось несколько месяцев, чтобы все исправить.

Если вы хотите понять, какие байты вы видите для оператора Tj, посмотрите на спецификацию PDF: http://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/ PDF32000_2008.pdf

Более конкретно – посмотрите раздел 9.4.3. Чтобы перефразировать этот раздел – каждый байт или потенциальная последовательность из нескольких байтов необходимо искать в шрифте, используемом для рисования текста (в вашем примере шрифт обозначается как / F1). Посмотрев его, вы обнаружите фактический символ, на который ссылается этот код.

Также имейте в виду, что порядок, в котором вы видите эти текстовые команды здесь, может вообще не отражать естественный порядок чтения, поэтому вам придется рассчитывать на основе позиций, которые вы находите, что на самом деле правильный порядок этих символов.

Также имейте в виду, что ваш файл PDF может не содержать пробелов, например. Поскольку пространство может быть «подделано» простым перемещением следующего символа вправо, некоторые генераторы PDF пропускают пробелы. Но найти пробел в координатах может не быть сломанным словом. Например, это может быть конец столбца.

Это действительно очень сложно – особенно если вы пытаетесь сделать это в общих файлах PDF (в отличие от всего лишь нескольких макетов, которые вы знаете, всегда из одного источника). Я написал текстовый редактор для PDF давно, для продукта под названием PitStop Pro, который все еще находится вокруг (больше не связан с ним), и это была очень сложная проблема.

Если это вариант, попробуйте использовать существующую библиотеку или инструмент. Есть, конечно, коммерческие варианты для такой библиотеки или инструмента; Я менее знаком с библиотеками с открытым исходным кодом / бесплатно, поэтому я не могу комментировать это.

  • Могу ли я создать виртуальную 3d-модель здания из двухмерных чертежей в формате PDF?
  • Пакетное преобразование изображений TIFF в PDF?
  • Извлечение изображения из PDF с помощью itextsharp
  • Добавление нескольких изображений в один файл PDF с помощью iText с использованием java
  • Из Word в PDF, включая закладки
  • Как узнать, встроены ли шрифты в PDF-файл или нет?
  • Сделать Chrome всегда открытым PDF-файлы
  • Как вызвать firefox встроенный просмотрщик pdf (pdf.js) вручную?
  • Как конвертировать 1-страничный PDF-файл в PDF-файл на 2 страницы?
  • Печать Pdf в C #
  • Правильный тип носителя MIME для файлов PDF
  • Interesting Posts

    Используйте регулярное выражение для соответствия любому китайскому символу в кодировке utf-8

    Logstash: как добавить имя файла в качестве поля?

    Как проверить, является ли тип объекта конкретным подclassом в C ++?

    Совместимая прокладка, используемая .NET Standard 2.0

    Является ли JPEG без потерь, когда для качества установлено значение 100?

    Как отменить / прервать запрос JQuery AJAX?

    Блокирует Console.WriteLine?

    Удалите повторяющиеся строки в excel, если не все столбцы одинаковы

    Spring Boot: невозможно запустить EmbeddedWebApplicationContext из-за отсутствия компонента EmbeddedServletContainerFactory

    андроид имитирует низкое сетевое подключение

    Как использовать маркеры SVG в API Карт Google v3

    Навсегда удалить папку с этого ПК

    Как я могу конвертировать секунды с эпохи в часы / минуты / секунды в Java?

    Внешний жесткий диск как его форматировать?

    Сохранить текстовый файл UTF-8, закодированный с помощью VBA

    Давайте будем гением компьютера.