No se pueden obtener caracteres checos mientras se genera un PDF

Tengo un problema al agregar caracteres como “Č” o “Ć” al generar un PDF. Casi siempre uso párrafos para insertar texto estático en mi informe PDF. Aquí hay un código de muestra que utilicé:

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

La salida que obtengo cuando se genera el archivo PDF se ve así: “Prueba de letras, Š, Ž, Đ”

Por alguna razón, iTextSharp no parece reconocer estas letras, como “Č” y “Ć”.

EL PROBLEMA:

En primer lugar, parece que no hablas de caracteres cirílicos, sino de idiomas de Europa central y del este que usan escritura latina. Eche un vistazo a la diferencia entre la página de códigos 1250 y la página de códigos 1251 para comprender a qué me refiero. [NOTA: He actualizado la pregunta para que hable de caracteres checos en lugar de cirílico.]

Segunda observación. Está escribiendo código que contiene caracteres especiales:

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

Esa es una mala práctica. Los archivos de código se almacenan como texto sin formato y se pueden guardar utilizando diferentes codificaciones. Un cambio accidental de la encoding (por ejemplo: al cargarlo en un sistema de control de versiones que usa una encoding diferente) puede dañar seriamente el contenido de su archivo.

Debe escribir código que no contenga caracteres especiales, pero que use anotaciones diferentes. Por ejemplo:

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

Esto también asegurará que el contenido no se altere al comstackr el código utilizando un comstackdor que espera una encoding diferente.

Su tercer error es suponer que Helvetica es una fuente que sabe cómo dibujar estos glifos. Esa es una suposición falsa. Debe usar un archivo de fuente como Arial.ttf (o elija cualquier otra fuente que sepa cómo dibujar esos glifos).

El cuarto error es que no incrusta la fuente. Supongamos que usa una fuente que tiene en su máquina local y que es capaz de dibujar los glifos especiales, entonces podrá leer el texto en su máquina local. Sin embargo, es posible que alguien que reciba su archivo, pero no tenga la fuente que usó en su máquina local, no pueda leer el documento correctamente.

El quinto error es que no definiste una encoding cuando usas la fuente (esto está relacionado con tu segundo error, pero es diferente).

LA SOLUCIÓN:

He escrito un pequeño ejemplo llamado CzechExample que da como resultado el siguiente PDF: czech.pdf

enter image description here

He agregado el mismo texto dos veces, pero usando una encoding diferente:

 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(); } 

Para evitar su tercer error, utilicé la fuente FreeSans.ttf en lugar de Helvetica. Puede elegir cualquier otra fuente siempre que admita los caracteres que quiera usar. Para evitar su cuarto error, he establecido el parámetro embedded en true .

En cuanto a su quinto error, presenté dos enfoques diferentes.

En el primer caso, le dije a iText que usara la página de códigos 1250.

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

Esto insertará la fuente como una fuente simple en el PDF, lo que significa que cada carácter de la String se representará con un solo byte . La ventaja de este enfoque es la simplicidad; la desventaja es que no debe comenzar a mezclar páginas de códigos. Por ejemplo: esto no funcionará para los glifos cirílicos.

En el segundo caso, le dije a iText que use Unicode para escritura horizontal:

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

Esto insertará la fuente como una fuente compuesta en el PDF, lo que significa que cada carácter en su String se representará utilizando más de un byte . La ventaja de este enfoque es que es el enfoque recomendado en los estándares PDF más nuevos (por ejemplo, PDF / A, PDF / UA), y que puede mezclar cirílico con latín, chino con japonés, etc. La desventaja es que usted crear más bytes, pero ese efecto está limitado por el hecho de que las secuencias de contenido se comprimen de todos modos.

Cuando descomprimo la secuencia de contenido para el texto en el PDF de muestra, veo la siguiente syntax de PDF:

enter image description here

Como ya expliqué, los bytes individuales se usan para almacenar el texto de la primera línea. Los bytes dobles se usan para almacenar el texto de la segunda línea.

Puede sorprenderse que estos personajes se vean bien por fuera (cuando se mira el texto en Adobe Reader), pero no se corresponden con lo que se ve en el interior (cuando se mira la segunda captura de pantalla), pero así es como funciona .

CONCLUSIÓN:

Muchas personas piensan que crear PDF es trivial, y que las herramientas para crear PDF deberían ser un producto básico. En realidad, no siempre es tan simple 😉