Не удается вставить табуляции и пробелы в PDF-документ PDBox

#java #pdf-generation #pdfbox #java-11

#java #PDF #javafx #шрифты #pdfbox

Вопрос:

Я хочу распечатать это в формате PDF, созданном PDFBOX. Это не позволит мне вставлять табуляции и пробелы, потому что шрифт их не поддерживает. Почему это проблема и, что более важно, как я могу это исправить?

 StudentData student = listOfDebtors.get(j);

contentStream.beginText();
contentStream.setFont(font, 8);
contentStream.newLineAtOffset(xPosition, yPosition);
contentStream.showText("Member #:"  student.getMembershipNumber()   "t"
              "Grade:"   getStudentGradeInSchool(student.getYearGraduate())   "t"
              "Year Joined"   student.getYearJoined()   "n" 
              "Name:"   student.getFirstName()   " "   student.getLastName()   "n"
              "Amount Owed : $"   student.getAmountOwed()); 
  

Показана ошибка:

 Caused by: java.lang.IllegalArgumentException: No glyph for U 0009 in font Courier
    at org.apache.pdfbox.pdmodel.font.PDType1Font.encode(PDType1Font.java:353)
    at org.apache.pdfbox.pdmodel.font.PDFont.encode(PDFont.java:283)
    at org.apache.pdfbox.pdmodel.PDPageContentStream.showText(PDPageContentStream.java:341)
    at fbla.rahulshah.database.dataManipulation.PDFCreator.createDebtorPDF(PDFCreator.java:61)
    at fbla.rahulshah.database.view.MainScreenController.generateDebtReport(MainScreenController.java:114)
    ... 62 more
  

Комментарии:

1. Это, безусловно, какой-то отдельный код. Генерирует ли это какие-либо ошибки? Если да, можете ли вы также показать ошибки?

2. добавлена ошибка, которую он показывает

3. Поскольку мы знаем, что шрифт real Courier содержит U 0009, следующий вопрос, который я предполагаю, «вы работаете с реальным Courier или производным подмножеством?», Потому что я уверен, что это последнее, и в этом случае вы не можете выполнять какие-либо изменения, которые используют глифы за пределами подмножества.

Ответ №1:

Шрифт — это набор символов. Не существует такого понятия, как «символ ТАБУЛЯЦИИ». Просто представьте, что вы набираете текст с помощью металлических символов 100 лет назад, и какой-то парень (у которого есть пишущая машинка) спрашивает вас о «символе табуляции».

В пишущей машинке нажатие TAB означает «перейти к следующей позиции табуляции». Шрифт не знает своего собственного положения, он знает только внешний вид и размер своих символов. В PDF или PDFBox также нет понятия «позиции табуляции». PDF или PDFBox не являются текстовыми редакторами.

И даже в редакторе слепое нажатие на ВКЛАДКУ не всегда доставляет вам удовольствие, в зависимости от длины текста, который вы только что написали. Сначала вам нужно будет проверить свою собственную позицию, а затем подумать о том, чтобы нажать TAB или, возможно, нажать его дважды.

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

Что подводит нас к следующей части, отсутствующему пробелу. Что ж, используйте другой шрифт с пробелами, потому что там есть символ пробела: он выглядит невидимым, но имеет фиксированный размер.

И, наконец, также нет такого понятия, как «символ новой строки». Новая строка — это команда. Вы уже используете «newLineAtOffset», который должен работать нормально, чтобы позиционировать себя. Смотрите ответ mkl о том, как это сделать.

Комментарии:

1. следующая часть, недостающий пробел — Учитывая исключение OP, я сомневаюсь, что существует реальная проблема с символами пробела.

2. @mkl да, возможно, но никто не знает, какие странные шрифты используют люди. И я хотел опубликовать разглагольствование для «всех очень запутанных людей», чтобы объяснить разницу между пробелом и табуляцией.

Ответ №2:

Причина в том, что PDPageContentStream.showText(String) может отображать только текст, он не может выполнять какие-либо дополнительные компоновки, такие как интерпретация горизонтальных вкладок, разрывов строк или других управляющих символов; Тилман подробно объяснил это в своем ответе.

Вы могли бы достичь своей цели с помощью чего-то вроде этого:

 contentStream.newLineAtOffset(xPosition, yPosition);
contentStream.showText("Member #: "  student.getMembershipNumber());
contentStream.newLineAtOffset(200, 0);
contentStream.showText("Grade: "   getStudentGradeInSchool(student.getYearGraduate()));
contentStream.newLineAtOffset(200, 0);
contentStream.showText("Year Joined: "   student.getYearJoined());
contentStream.newLineAtOffset(-400, -12);
contentStream.showText("Name: "   student.getFirstName()   " "   student.getLastName());
contentStream.newLineAtOffset(0, -12);
contentStream.showText("Amount Owed: $"   student.getAmountOwed());