Невозможно получить чешских персонажей при создании PDF файла

У меня проблема при добавлении символов, таких как "Č" или "Ć", при создании PDF. В основном я использую абзацы для вставки некоторого статического текста в свой PDF-отчет. Вот пример кода, который я использовал:

var document = new Document();
document.Open();
Paragraph p1 = new Paragraph("Testing of letters Č,Ć,Š,Ž,Đ", new Font(Font.FontFamily.HELVETICA, 10));
document.Add(p1);

Результат, который я получаю при создании файла PDF, выглядит следующим образом: "Тестирование букв, Š, Ž, Đ"

По какой-то причине iTextSharp, похоже, не распознает эти буквы, такие как "Č" и "Ć".

Ответ 1

ПРОБЛЕМА:

Сначала, вы, кажется, не говорите о кириллических персонажах, а о центральных и восточноевропейских языках, которые используют латинский script. Взгляните на разницу между code page 1250 и code page 1251 понять, что я имею в виду. [ПРИМЕЧАНИЕ. Я обновил вопрос, чтобы он говорил о чешских персонажах вместо кириллицы.]

Второе наблюдение. Вы пишете код, содержащий специальные символы:

"Testing of letters Č,Ć,Š,Ž,Đ"

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

Вы должны написать код, который не содержит специальных символов, но которые используют разные обозначения. Например:

"Testing of letters \u010c,\u0106,\u0160,\u017d,\u0110"

Это также гарантирует, что содержимое не будет изменено при компиляции кода с использованием компилятора, который ожидает другую кодировку.

Ваша третья ошибка заключается в том, что вы предполагаете, что Helvetica - это шрифт, который знает, как рисовать эти глифы. Это ложное предположение. Вы должны использовать файл шрифта, такой как Arial.ttf(или выбрать любой другой шрифт, который знает, как рисовать эти глифы).

Ваша ошибка четвертая заключается в том, что вы не вставляете шрифт. Предположим, что вы используете шрифт, который у вас есть на вашей локальной машине, и который может нарисовать специальные глифы, тогда вы сможете прочитать текст на своем локальном компьютере. Тем не менее, кто-то, кто получает ваш файл, но не имеет шрифта, который вы использовали на его локальной машине, возможно, не сможет правильно прочитать документ.

Ваша ошибка пятая заключается в том, что вы не определяли кодировку при использовании шрифта (это связано с вашей второй ошибкой, но оно отличается).

РЕШЕНИЕ:

Я написал небольшой пример под названием CzechExample, который приводит к следующему PDF: czech.pdf

enter image description here

Я добавил один и тот же текст дважды, но с использованием другой кодировки:

public static final String FONT = "resources/fonts/FreeSans.ttf";
public void createPdf(String dest) throws IOException, DocumentException {
    Document document = new Document();
    PdfWriter.getInstance(document, new FileOutputStream(DEST));
    document.open();
    Font f1 = FontFactory.getFont(FONT, "Cp1250", true);
    Paragraph p1 = new Paragraph("Testing of letters \u010c,\u0106,\u0160,\u017d,\u0110", f1);
    document.add(p1);
    Font f2 = FontFactory.getFont(FONT, BaseFont.IDENTITY_H, true);
    Paragraph p2 = new Paragraph("Testing of letters \u010c,\u0106,\u0160,\u017d,\u0110", f2);
    document.add(p2);
    document.close();
}

Чтобы избежать вашей третьей ошибки, я использовал шрифт FreeSans.ttf вместо Helvetica. Вы можете выбрать любой другой шрифт, если он поддерживает символы, которые вы хотите использовать. Чтобы избежать вашей четвертой ошибки, я установил параметр embedded в true.

Что касается вашей пятой ошибки, я представил два разных подхода.

В первом случае я сказал iText использовать кодовую страницу 1250.

Font f1 = FontFactory.getFont(FONT, "Cp1250", true);

Это добавит шрифт в качестве простого шрифта в PDF, что означает, что каждый символ в вашем String будет представлен с использованием одного байта. Преимущество такого подхода заключается в простоте; недостатком является то, что вы не должны начинать смешивать кодовые страницы. Например: это не будет работать для кириллических символов.

Во втором случае я сказал iText использовать Unicode для горизонтальной записи:

Font f2 = FontFactory.getFont(FONT, BaseFont.IDENTITY_H, true);

Это добавит шрифт в виде сложного шрифта в PDF, что означает, что каждый символ в вашем String будет представлен с использованием более одного байта. Преимущество такого подхода заключается в том, что это рекомендуемый подход в новых стандартах PDF (например, PDF/A, PDF/UA) и что вы можете смешивать кириллицу с латинским, китайским и японским и т.д. Недостатком является то, что вы создайте больше байтов, но этот эффект ограничен тем, что потоки контента все равно сжаты.

Когда я распаковываю поток контента для текста в примере PDF, я вижу следующий синтаксис PDF:

enter image description here

Как я объяснил, для хранения текста первой строки используются одиночные байты. Двойные байты используются для хранения текста второй строки.

Вы можете быть удивлены, что эти символы выглядят нормально снаружи (при просмотре текста в Adobe Reader), но не соответствуют тому, что вы видите внутри (при просмотре второго снимка экрана), но это как это работает.

ВЫВОД:

Многие думают, что создание PDF тривиально, и что инструменты для создания PDF должны быть товаром. На самом деле это не всегда так просто: -)