Причина в том, что PDFTextStripper
не просто организует объекты TextPosition
, которые он извлекает из базового анализатора, в строки и добавляет подразумеваемые пробелы, но также выполняет некоторую дополнительную предварительную обработку на них перед пересылкой на writeString
.В частности, он
- подавляет дублирующиеся перекрывающиеся глифы: один из способов создать смелый эффект для бедняков - это рисовать глифы дважды с небольшим смещением, и эти дубликаты подавляются;и
- объединяет
TextPosition
объекты, содержащие диакритический знак, с TextPosition
, содержащим соответствующий базовый глиф, в TextPosition
, представляющий объединенную кодовую точку Unicode.
Прежняя обработкашаг может быть отключен с помощью PDFTextStripper.setSuppressDuplicateOverlappingText(false)
, но последний не может.
Эффект, который вы наблюдаете, связан с последним шагом обработки.
Если вы хотите получить глифы без какой-либо предварительной обработки, т.е. без подавления дубликатов и диакритического слияния, а также без их организации в строки и добавления неявных пробелов, вы можете переопределить processTextPosition
вместо writeString
:
PDDocument document = PDDocument.load(resource);
PDFTextStripper stripper = new PDFTextStripper() {
@Override
protected void processTextPosition(TextPosition textPosition) {
try {
writeString(String.format("%s%s", textPosition.getUnicode(), Arrays.toString(textPosition.getCharacterCodes())));
} catch (IOException e) {
e.printStackTrace();
}
}
};
String text = stripper.getText(document);
( ExtractCharacterCodes test testExtractFromPattern3
)
Результат для вашего примера документа теперь будет
स[1434]ु[1441]न[1418] [3]त[1414]स्[7021]क[1399]र[1426]ी[1440]क[1399]ा[1438] [3]...
Если вы все еще хотите, чтобы PDFTextStripper
организовалГлифы в строки и добавление подразумеваемых пробелов, вы должны исправить этот класс (или свою собственную копию) и в конце его реализации processTextPosition
отключить слияние диакритических знаков, заменив
// test if we overlap the previous entry.
// Note that we are making an assumption that we need to only look back
// one TextPosition to find what we are overlapping.
// This may not always be true. */
TextPosition previousTextPosition = textList.get(textList.size() - 1);
if (text.isDiacritic() && previousTextPosition.contains(text))
{
previousTextPosition.mergeDiacritic(text);
}
// If the previous TextPosition was the diacritic, merge it into this
// one and remove it from the list.
else if (previousTextPosition.isDiacritic() && text.contains(previousTextPosition))
{
text.mergeDiacritic(previousTextPosition);
textList.remove(textList.size() - 1);
textList.add(text);
}
else
{
textList.add(text);
}
простым
textList.add(text);
Кстати, ваш тестовый файл выдает ошибку в определении PDFBox базового глифа для слияния диакритического знака с: "स [1434] ु [1441] न [1418] "предназначено для отображения в виде" सुन ", т. Е. Знак гласного u" ु "объединяется с буквой sa" स ", но PDFBox объединяет его с последующей буквой na" न "как "सनु".
Причина заключается в том, что оно определяет букву, с которой соединяется диакритический знак, по своему происхождению, которое здесь действительно находится в диапазоне последней буквы na "न", но в качестве символа гласногоОтрисованный до его происхождения (он рисуется в области с отрицательной x координатой), PDFBox определяет неправильную связь:
![SA-U-NA](https://i.stack.imgur.com/JwQyC.png)