2013-04-12 2 views
6

я пытаюсь изменить PDF с помощью этого метода (первый блок кода - с помощью PDFStreamParser и переборе PDFOperator, то обновление COSString при необходимости):Java PDFBox - Чтение и изменение PDF со специальными символами (диакритические)

http://www.coderanch.com/t/556009/open-source/PdfBox-Replace-String-double-pdf

У меня возникли проблемы с некоторыми UTF-8 символов (диакритические): «?», когда я печатаю текст, который я хочу, чтобы обновить его показать, как «?? Societ II Na ionale» (где код типа 0002 или 0004).

Забавные вещи:

  1. , когда я пишу обновленный файл PDF, персонажи шоу правильно (даже если я could't обнаружены и заменить их)
  2. если я пытаюсь лишить текст используя getText()) PDFTextStripper, текст отлично извлекается.
  3. Я попробовал 2 версии pdfbox: 1.5.0 (что ведет себя так, как описано выше) и 1.8.1 (где окончательный, написанный, pdf-файл не отображает специальные символы правильно, и в документе появляются «нулевые» строки)

Что я могу сделать (настроить) для классов, используемых для обновления pdf (или, по крайней мере, попробовать ...), чтобы все символы UTF-8 отображались правильно?

EDIT:

Скриншот: enter image description here

EDIT 2:

Я искал через исходный pdfbox код в PDFTextStripper и его суперкласса, и я узнал, как был извлечен текст:

В начале технологического процесса мы имеем

graphicsState = new PDGraphicsState(aPage.findCropBox()); 

при зачистке текст в processEncodedText, экземпляр класса PDFont используется следующим образом:

final PDFont font = graphicsState.getTextState().getFont(); 

и текст извлекается из байта [] с:

String c = font.encode(string, i, codeLength); 

Новая проблема заключается в том, что когда я создаю класс PDFont с теми же двумя строками кода, я получаю «нулевой» класс шрифтов, и поэтому я не могу использовать метод .encode (...). Исходный код для этих классов здесь: http://grepcode.com/file/repo1.maven.org/maven2/org.apache.pdfbox/pdfbox/1.5.0/org/apache/pdfbox/util/PDFStreamEngine.java и http://grepcode.com/file/repo1.maven.org/maven2/org.apache.pdfbox/pdfbox/1.5.0/org/apache/pdfbox/util/PDFTextStripper.java

Я рою теперь больше ...

+0

давайте возьмем каждый за раз. Поэтому, когда вы печатаете текст, содержащий некоторые диакритики, он отображается с помощью ??? или некоторые цифры вместо этого? Можете ли вы привести пример своих заявлений на печать, а также некоторые результаты? – Eugene

+0

Код замены строки, который вы нашли [здесь, на coderanch] (http: //www.coderanch.com/t/556009/open-source/PdfBox-Replace-String-double-pdf) вряд ли работает: 1. Кодирование строк в содержимом PDF-страниц полностью зависит от соответствующего шрифта; ваш код предполагает стандартную кодировку. 2. Буквы одного слова (или заполнителя в данном случае) могут распространяться на несколько строк в потоке контента; ваш код не найдет таких разделенных заполнителей. 3. Шрифты могут быть частично встроены в PDF; если ваша строка замены использует символы, которые не используются иным образом, они не будут отображаться. ... – mkl

+0

@Eugene: текст отображается правильно, за исключением диакритических знаков, которые отображаются как квадраты с 4 цифрами (два сверху - например, 00, два внизу, например, 02). Я не могу вырезать/вставлять вывод в браузер (потому что они будут отображаться как пробелы), но я приложу скриншот с выходом в консоли Eclipse. –

ответ

1

Наконец, это означает, что процесс извлечения шрифтов в файле pdf довольно сложен. Я не мог использовать шрифты явно, поэтому я искал внутри кода PDFStreamEngine и классы, расширяющие OperatorProcessor, и выяснял, как объекты PDFont были созданы на карте (я в значительной степени копировал фрагменты кода, которые мне нужны для извлечения диакритики) , Итак, после этого я использовал обнаруженные шрифты при взаимодействии через parser.getTokens() для вызова метода encode (...) для каждого символа в строке.

+0

Как вы можете получить шрифт и закодировать строку? Я имею дело с китайской строкой и встретил ту же проблему. – hwding

17

Вы не можете просто заменить текст в строках. Я не говорю это легкомысленно. Я работал над Acrobat много лет назад и использовал инструмент текстового поиска в начальной версии, поэтому у меня довольно глубокое понимание проблем текстовой кодировки. Основная проблема заключается в том, что каждая строка в формате PDF каким-то образом закодирована. Это связано с тем, что PDF был сделан до того, как Unicode был вообще доступен и имел историю в PostScript. PosctScript любил иметь очень гибкие методы кодирования для шрифтов и поощрять повторное кодирование.

Итак, давайте сделаем шаг назад и поймем всю картину.

Символ в строке в формате PDF, который предназначен для отображения текстовым оператором, по умолчанию кодируется как серия из 8 бит символов. Чтобы определить, какой глиф рисуется для каждого байта, байт проталкивается через вектор кодирования для этого шрифта. Вектор кодирования сопоставляет байту имя глифа, которое затем просматривается в шрифте и нарисовано на странице. Имейте в виду, что это описание является полуправдой (более поздним).

Большинство приложений, которые генерируют PDF, являются добрыми и используют стандартную кодировку, такую ​​как StandardEncoding или WinAnsiEncoding, большинство из которых довольно разумны. Другие будут использовать стандартные кодировки вместе с кодировкой delta, которые являются отличиями от стандартного кодирования от того, что закодировано.

Некоторые приложения стараются быть более экономными в PDF-формате, который они создают, поэтому они просматривают глифы, которые они используют, и принимают решение о встраивании подмножества шрифта. Если они используют только буквы и цифры в верхнем и нижнем регистре, они перестраивают шрифт без этих элементов и могут также повторно индексировать их и предоставить вектор кодирования, так что байт 0x00 переходит к глифу 'a', а 0x01 переходит в глиф 'b' и т. д.

Теперь вернемся к половине истины. Существует класс шрифтов, которые кодируются символьным идентификатором (или CID), а шрифты TrueType и OpenType попадают в эту категорию. В этом случае вы получаете доступ к Unicode, но опять же есть шаг кодирования, где вы, строка, которая теперь является UTF16BE, сопоставляется с CID, который используется для получения глифа шрифта. И без особого основания Adobe использует функцию PostScript для отображения. И снова это правда о 3/4s, потому что для кодирования китайского, японского и корейского шрифтов существуют разные кодировки.

Поэтому, прежде чем беспечно поместить символ в строку для PDF шрифта, вы должны задать несколько вопросов:

  1. Является ли мои глифы в шрифте?
  2. Является ли мой глиф в кодировке?
  3. Что такое кодировка моего глифа?

И любой из них может отличаться от ожидаемого. Так, например, если вы хотите поместить в Ä (diresis), вы должны увидеть, есть ли у шрифта глиф (что может быть не там, потому что шрифт является подмножеством). Тогда шрифт может иметь смешную кодировку, которая может не содержать глифа. И, наконец, фактическое значение байтов для использования для Ä может быть не стандартным.

Поэтому, когда я вижу, что кто-то пытается просто заменить кусок текста в формате PDF, все, что я вижу, это мир боли. Для большинства нормальных PDF это будет работать, скажем, в 90% случаев, но для чего-то экзотического - удачи. Отличия от текста в тексте PDF настолько болезненны, что иногда легче думать об этом как о формате для записи.

+0

Спасибо за ваш ответ. Я также обновил свой вопрос с некоторыми выводами относительно строк кода в pdfbox, связанных с классом, который извлекает текст правильно из моих файлов PDF. –

+0

@plinth этот ответ, скорее всего, не будет слишком большим, но для меня он заслуживает золотой партии. – Eugene

Смежные вопросы