Suporte Unicode

No JasperReports, trabalhar com textos precisa de algumas ferramentas dedicadas para processar tanto as representações de caracteres quanto as propriedades de formatação de texto. Qualquer texto pode ser considerado uma sequência de caracteres com uma estrutura de representação particular. A aparência do texto consiste em configurações de layout (e parágrafo) e fonte. Mas embora, na maioria dos casos, o layout do texto permaneça invariável, as configurações de fonte podem mudar ao executar o relatório em diferentes localidades.

Sabemos que idiomas diferentes precisam de conjuntos de caracteres diferentes com respeito à representação de caracteres específicos. Portanto, trabalhar com textos significa trabalhar com fontes. No entanto, uma discussão detalhada sobre como usar fontes no JasperReports está disponível no capítulo Fontes de relatório .

Uma das principais características do conteúdo do texto de um determinado relatório é a possibilidade de internacionalizá-lo. Isso significa que podemos executar o relatório em diferentes ambientes localizados, usando diferentes idiomas e outras configurações de localização sem nenhuma modificação codificada. A codificação de caracteres é um recurso importante quando um relatório se destina a ser internacionalizado.

Codificação de Caracteres

Um personagem é a menor unidade de escrita que transmite uma informação significativa. É um conceito abstrato, um personagem não tem uma aparência visual. "A maiúsculo latino" é um caractere diferente de "a latino minúsculo" e de "A cirílico maiúsculo" e "Alfa grego maiúsculo".

A representação visual de um personagem é conhecida como glyph. Um certo conjunto de glifos é chamado defont. "Letras maiúsculas A latino", "letras maiúsculas cirílico A" e "letras maiúsculas e alfa grego" podem ter glifos idênticos, mas são caracteres diferentes. Ao mesmo tempo, os glifos para "A maiúsculo em latim" podem parecer muito diferentes em Times New Roman, Gill Sans e Poetica chancery itálico, mas ainda representam o mesmo caractere.

O conjunto de personagens disponíveis é denominado repertório de personagens . A localização (índice) de um determinado personagem em um repertório é conhecida como sua posição de código ou ponto de código. O método de representar numericamente um ponto de código dentro de um determinado repertório é chamado decharacter encoding.

As codificações são normalmente expressas em termos de octetos. Um octeto é um grupo de oito dígitos binários, ou seja, oito uns e zeros. Um octeto pode expressar um intervalo numérico entre 0 e 255, ou entre 0x00 e 0xFF, para usar a notação hexadecimal.

Unicode

Um Unicode é um repertório de caracteres que contém a maioria dos caracteres usados ​​nas línguas do mundo. Ele pode acomodar milhões de caracteres e já contém centenas de milhares. O Unicode é dividido em "planos" de 64K caracteres. O único usado na maioria das circunstâncias é o primeiro plano, conhecido como plano multilíngue básico ou BMP.

UTF-8 é a codificação recomendada. Ele usa um número variável de octetos para representar caracteres diferentes.

Em um arquivo JRXML, o atributo de codificação é especificado no cabeçalho. Ele é usado no momento da compilação do relatório para decodificar o conteúdo XML. Por exemplo, se o relatório contém apenas palavras em francês e caracteres como ç, é, â, então a codificação ISO-8859-1 (também conhecida como Latin-1) é suficiente -

<?xml version = "1.0" encoding = "ISO-8859-1"?>

Como visto acima, idealmente podemos escolher o ajuste de codificação para o conjunto mínimo de caracteres, que pode representar corretamente todos os caracteres no documento. Mas no caso de documentos multilíngues (ou seja, documentos contendo palavras escritas em vários idiomas), deve-se escolher a codificação adaptada ao conjunto mínimo de caracteres, capaz de representar corretamente todos os caracteres do documento, mesmo que pertençam a idiomas diferentes. Uma das codificações de caracteres capazes de lidar com documentos multilíngues é oUTF-8, usado como valor de codificação padrão por JasperReports.

Os textos são geralmente mantidos em arquivos de pacote de recursos, e não no documento durante a internacionalização. Portanto, há casos em que o próprio JRXML parece completamente compatível com ASCII, mas os relatórios gerados em tempo de execução contêm textos ilegíveis com ASCII. Como resultado, para um determinado tipo de formato de exportação de documento (como CSV, HTML, XHTML, XML e texto), é necessário conhecer também a codificação do documento gerado. Idiomas diferentes são suportados por diferentes codificações de caracteres. Portanto, a cada vez, precisamos executar um relatório em um ambiente localizado. Além disso, precisamos saber qual é a codificação de caracteres mais apropriada para a linguagem do documento gerado. Nesse caso, a propriedade de codificação definida no próprio arquivo JRXML pode não ser mais útil.

Para resolver esse tipo de problema, podemos usar uma propriedade de cliente de exportação conhecida como net.sf.jasperreports.export.character.encoding . Esta propriedade customizada de exportação é padrão para UTF-8 e está presente no JasperReports.

Este valor padrão é configurado no arquivo default.jasperreports.properties . Para opções mais específicas no momento da exportação, o parâmetro de exportação CHARACTER_ENCODING também está disponível.

Exemplo

Para demonstrar o uso do suporte a Unicode no Jasperreports, vamos escrever um novo modelo de relatório (jasper_report_template.jrxml). Save it to C:\tools\jasperreports-5.0.1\testdiretório. Aqui, exibiremos um texto em diferentes idiomas usando os caracteres Unicode (\ uXXXX). Qualquer caractere codificado com UTF-8 pode ser representado usando apenas seu código hexadecimal de 4 dígitos. Por exemplo, a letra grega Γ pode ser escrita como \ u0393. Quando tal notação é encontrada, o mecanismo pede a representação de caractere apropriada no conjunto de caracteres, e somente aquele caractere particular será impresso. O conteúdo do JRXML é o seguinte -

<?xml version = "1.0" encoding = "UTF-8"?>

<jasperReport xmlns = "http://jasperreports.sourceforge.net/jasperreports"
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation = "http://jasperreports.sourceforge.net/jasperreports
   http://jasperreports.sourceforge.net/xsd/jasperreport.xsd"
   name = "jasper_report_template" language = "groovy" pageWidth = "595"
   pageHeight = "842" columnWidth = "555" leftMargin = "20" rightMargin = "20"
   topMargin = "20" bottomMargin = "20">

   <parameter name = "GreekText" class = "java.lang.String" isForPrompting = "false">
      <defaultValueExpression><![CDATA["\u0394\u03B5\u03BD "+
         "\u03BA\u03B1\u03C4\u03B1\u03BB\u03B1\u03B2\u03B1\u03AF"+
         "\u03BD\u03C9 \u0395\u03BB\u03BB\u03B7\u03BD\u03B9\u03BA\u03AC"]]>
      </defaultValueExpression>
   </parameter>
   
   <parameter name = "CyrillicText" class = "java.lang.String" isForPrompting = "false">
      <defaultValueExpression><![CDATA["\u042F \u043D\u0435 "+
         "\u043C\u043E\u0433\u0443 \u043F\u043E\u043D\u044F\u0442\u044C "+
         "\u0433\u0440\u0435\u0447\u0435\u0441\u043A\u0438\u0439"]]>
      </defaultValueExpression>
   </parameter>

   <parameter name = "ArabicText" class = "java.lang.String" isForPrompting = "false">
      <defaultValueExpression><![CDATA["\u0627\u0646\u0646\u0649 \u0644\u0627 "+
         "\u0627\u0641\u0647\u0645 \u0627\u0644\u0644\u063A\u0629 "+
         "\u0627\u0644\u0639\u0631\u0628\u064A\u0629"]]>
      </defaultValueExpression>
   </parameter>
   
   <parameter name = "HebrewText" class = "java.lang.String" isForPrompting = "false">
      <defaultValueExpression><![CDATA["\u05D0\u05E0\u05D9 \u05DC\u05D0 "+
         "\u05DE\u05D1\u05D9\u05DF \u05E2\u05D1\u05E8\u05D9\u05EA"]]>
      </defaultValueExpression>
   </parameter>
   
   <title>
      <band height = "782">
         
         <textField>
            <reportElement x = "0" y = "50" width = "200" height = "60"/>
            
            <textElement>
               <font fontName = "DejaVu Sans" size = "14"/>
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$P{GreekText} + "\n" + $P{CyrillicText}]]>
            </textFieldExpression>
         </textField>
         
         <staticText>
            <reportElement x = "210" y = "50" width = "340" height = "60"/>
            <textElement/>
            
            <text>
               <![CDATA["GreekText and CyrillicText"]]>
            </text>
         </staticText>
         
         <textField>
            <reportElement x = "0" y = "120" width = "200" height = "60"/>
            
            <textElement>
               <font fontName = "DejaVu Sans" size = "14" isBold = "true"/>
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$P{GreekText} + "\n" + $P{CyrillicText}]]>
            </textFieldExpression>
				
         </textField>
         
         <staticText>
            <reportElement x = "210" y = "120" width = "340" height = "60"/>
            <textElement/>
            <text><![CDATA["GreekText and CyrillicText"]]></text>
         </staticText>
         
         <textField>
            <reportElement x = "0" y = "190" width = "200" height = "60"/>
            
            <textElement>
               <font fontName = "DejaVu Sans" size = "14" isItalic = "true" 
                  isUnderline = "true"/>
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$P{GreekText} + "\n" + $P{CyrillicText}]]>
            </textFieldExpression>
				
         </textField>
         
         <staticText>
            <reportElement x = "210" y = "190" width = "340" height = "60"/>
            <textElement/>
            <text><![CDATA["GreekText and CyrillicText"]]></text>
         </staticText>
         
         <textField>
            <reportElement x = "0" y = "260" width = "200" height = "60"/>
            
            <textElement>
               <font fontName = "DejaVu Sans" size = "14" isBold = "true" 
                  isItalic = "true" isUnderline = "true"/>
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$P{GreekText} + "\n" + $P{CyrillicText}]]>
            </textFieldExpression>
				
         </textField>
         
         <staticText>
            <reportElement x = "210" y = "260" width = "340" height = "60"/>
            <textElement/>
            <text><![CDATA["GreekText and CyrillicText"]]></text>
         </staticText>

         <textField>
            <reportElement x = "0" y = "330" width = "200" height = "60"/>
            
            <textElement textAlignment = "Right">
               <font fontName="DejaVu Sans" size = "22"/>
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$P{ArabicText}]]>
            </textFieldExpression>
				
         </textField>
         
         <textField>
            <reportElement x = "210" y = "330" width = "340" height = "60"/>
            
            <textElement textAlignment = "Right">
               <font fontName = "DejaVu Sans" size = "22"/>
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$P{HebrewText}]]>
            </textFieldExpression>
				
         </textField>
      
      </band>
   </title>
	
</jasperReport>

No arquivo acima, podemos ver a presença da codificação UTF-8. Além disso, as partes de texto Unicode localizadas são armazenadas nos parâmetros do documento.

O código java para preencher e gerar o relatório é o seguinte. Vamos salvar este arquivoJasperUnicodeReportFill.java para o diretório C: \ tools \ jasperreports-5.0.1 \ test \ src \ com \ tutorialspoint.

package com.tutorialspoint;

import net.sf.jasperreports.engine.JREmptyDataSource;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperFillManager;

public class JasperUnicodeReportFill {
   public static void main(String[] args) {
      String sourceFileName ="C://tools/jasperreports-5.0.1/test/" + 
         "jasper_report_template.jasper";

      try {
         JasperFillManager.fillReportToFile(sourceFileName, null, 
            new JREmptyDataSource());
      } catch (JRException e) {
         // TODO Auto-generated catch block
         e.printStackTrace();
      }

   }
}

Aqui, usamos uma instância de JREmptyDataSource ao preencher relatórios para simular uma fonte de dados com um registro, mas com todos os campos neste único registro sendo nulos .

Geração de relatório

Vamos compilar e executar o arquivo acima usando nosso processo normal de construção ANT. O conteúdo do arquivo build.xml (salvo no diretório C: \ tools \ jasperreports-5.0.1 \ test) é o seguinte.

O arquivo de importação - baseBuild.xml é escolhido no capítulo Configuração do ambiente e deve ser colocado no mesmo diretório que o build.xml.

<?xml version = "1.0" encoding = "UTF-8"?>
<project name = "JasperReportTest" default = "viewFillReport" basedir = ".">
   <import file = "baseBuild.xml" />
   
   <target name = "viewFillReport" depends = "compile,compilereportdesing,run"
      description = "Launches the report viewer to preview the report 
      stored in the .JRprint file.">
      
      <java classname = "net.sf.jasperreports.view.JasperViewer" fork = "true">
         <arg value = "-F${file.name}.JRprint" />
         <classpath refid = "classpath" />
      </java>
		
   </target>
   
   <target name = "compilereportdesing" description = "Compiles the JXML file and
      produces the .jasper file.">
      
      <taskdef name = "jrc" classname = "net.sf.jasperreports.ant.JRAntCompileTask">
         <classpath refid = "classpath" />
      </taskdef>
      
      <jrc destdir = ".">
         <src>
            <fileset dir = ".">
               <include name = "*.jrxml" />
            </fileset>
         </src>
         <classpath refid = "classpath" />
      </jrc>

   </target>
	
</project>

A seguir, vamos abrir a janela da linha de comando e ir para o diretório onde build.xml está colocado. Finalmente, execute o comandoant -Dmain-class=com.tutorialspoint.JasperUnicodeReportFill (viewFullReport é o destino padrão) da seguinte forma -

C:\tools\jasperreports-5.0.1\test>ant  -Dmain-class=com.tutorialspoint.JasperUnicodeReportFill
Buildfile: C:\tools\jasperreports-5.0.1\test\build.xml

clean-sample:
   [delete] Deleting directory C:\tools\jasperreports-5.0.1\test\classes
   [delete] Deleting: C:\tools\jasperreports-5.0.1\test\jasper_report_template.jasper
   [delete] Deleting: C:\tools\jasperreports-5.0.1\test\jasper_report_template.jrprint

compile:
   [mkdir] Created dir: C:\tools\jasperreports-5.0.1\test\classes
   [javac] C:\tools\jasperreports-5.0.1\test\baseBuild.xml:28:
   warning: 'includeantruntime' was not set, defaulting t
   [javac] Compiling 1 source file to C:\tools\jasperreports-5.0.1\test\classes

compilereportdesing:
   [jrc] Compiling 1 report design files.
   [jrc] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.engine.xml.JRXmlDigesterFactory).
   [jrc] log4j:WARN Please initialize the log4j system properly.
   [jrc] log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
   [jrc] File : C:\tools\jasperreports-5.0.1\test\jasper_report_template.jrxml ... OK.

run:
   [echo] Runnin class : com.tutorialspoint.JasperUnicodeReportFill
   [java] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.extensions.ExtensionsEnvironment).
   [java] log4j:WARN Please initialize the log4j system properly.

viewFillReport:
   [java] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.extensions.ExtensionsEnvironment).
   [java] log4j:WARN Please initialize the log4j system properly.

BUILD SUCCESSFUL
Total time: 4 minutes 1 second

Como resultado da compilação acima, uma janela JasperViewer é aberta conforme mostrado na tela abaixo -

Aqui, podemos ver que o texto exibido está em diferentes idiomas. Também vemos que os idiomas estão agrupados na mesma página e também misturados no mesmo elemento de texto.