Obsługa Unicode

W JasperReports praca z tekstami wymaga specjalnych narzędzi do przetwarzania zarówno reprezentacji znaków, jak i właściwości formatowania tekstu. Każdy tekst może być traktowany jako ciąg znaków o określonej strukturze reprezentacji. Wygląd tekstu składa się zarówno z układu (i akapitu), jak i ustawień czcionki. Ale chociaż w większości przypadków układ tekstu pozostaje niezmienny, ustawienia czcionek mogą ulec zmianie podczas uruchamiania raportu w różnych lokalizacjach.

Wiemy, że różne języki wymagają różnych zestawów znaków w odniesieniu do określonych reprezentacji znaków. Dlatego praca z tekstami oznacza pracę z czcionkami. Jednak szczegółowe omówienie sposobu korzystania z czcionek w JasperReports jest dostępne w rozdziale Czcionki raportów .

Jedną z głównych cech dotyczących treści tekstu w danym raporcie jest możliwość jego umiędzynarodowienia. Oznacza to, że możemy uruchomić raport w różnych zlokalizowanych środowiskach, używając różnych języków i innych ustawień lokalizacyjnych bez żadnych zmian na stałe. Kodowanie znaków jest ważną funkcją, gdy raport ma być umiędzynarodowiony.

Kodowanie znaków

Znak to najmniejsza jednostka pisma zawierająca znaczącą informację. Jest to koncepcja abstrakcyjna, postać nie ma wyglądu. „Wielka litera łacińska A” to inny znak niż „mała litera łacińska a” oraz „wielka litera cyrylicy A” i „wielka grecka alfa”.

Wizualna reprezentacja postaci jest znana jako glyph. Pewien zestaw glifów nazywany jest afont. „Wielkie litery alfabetu łacińskiego A”, „wielkie litery cyrylicy A” i „wielkie litery alfabetu greckiego” mogą mieć identyczne glify, ale są to różne znaki. W tym samym czasie glify „wielkiej łaciny A” mogą wyglądać zupełnie inaczej w czcionkach Times New Roman, Gill Sans i Poetica chancery italic, ale nadal przedstawiają ten sam znak.

Zestaw dostępnych znaków nazywany jest repertuarem postaci . Lokalizacja (indeks) danego znaku w repertuarze jest znana jako jego pozycja kodowa lub punkt kodowy. Metoda numerycznego reprezentowania punktu kodowego w ramach danego repertuaru nosi nazwęcharacter encoding.

Kodowania są zwykle wyrażane w oktetach. Oktet to grupa ośmiu cyfr binarnych, tj. Ośmiu jedynek i zer. Oktet może wyrazić zakres liczbowy od 0 do 255 lub od 0x00 do 0xFF, aby użyć notacji szesnastkowej.

Unicode

Unicode to repertuar znaków, który zawiera większość znaków używanych w językach świata. Może pomieścić miliony postaci i zawiera już setki tysięcy. Unicode jest podzielony na „płaszczyzny” o długości 64 tys. Znaków. Jedynym używanym w większości przypadków jest pierwszy samolot, znany jako podstawowa płaszczyzna wielojęzyczna lub BMP.

UTF-8 jest zalecanym kodowaniem. Używa zmiennej liczby oktetów do reprezentowania różnych znaków.

W pliku JRXML atrybut kodowania jest określony w nagłówku. Jest używany w czasie kompilacji raportu do dekodowania zawartości XML. Na przykład, jeśli raport zawiera tylko francuskie słowa i znaki takie jak ç, é, â, kodowanie ISO-8859-1 (aka Latin-1) jest wystarczające -

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

Jak widać powyżej, idealnie byłoby dobrać kodowanie do minimalnego zestawu znaków, który może poprawnie reprezentować wszystkie znaki w dokumencie. Natomiast w przypadku dokumentów wielojęzycznych (tj. Dokumentów zawierających słowa pisane w kilku językach) należy wybrać kodowanie dostosowane do minimalnego zestawu znaków, zdolnego do poprawnej reprezentacji wszystkich znaków w dokumencie, nawet jeśli należą one do różnych języków. Jednym z kodowań znaków obsługujących dokumenty wielojęzyczne jestUTF-8, używana jako domyślna wartość kodowania przez JasperReports.

Teksty są zwykle przechowywane w plikach pakietów zasobów, a nie w dokumencie podczas internacjonalizacji. Są więc przypadki, w których sam JRXML wygląda na całkowicie zgodny z ASCII, ale raporty generowane w czasie wykonywania zawierają teksty nieczytelne w ASCII. W rezultacie w przypadku określonego typu formatów eksportu dokumentów (takich jak CSV, HTML, XHTML, XML i tekst) należy również znać kodowanie wygenerowanego dokumentu. Różne języki są obsługiwane przez różne kodowania znaków. Dlatego za każdym razem musimy uruchomić raport w zlokalizowanym środowisku. Ponadto musimy wiedzieć, które kodowanie znaków jest najbardziej odpowiednie dla generowanego języka dokumentu. W takim przypadku właściwość kodowania zdefiniowana w samym pliku JRXML może nie być już użyteczna.

Aby rozwiązać tego rodzaju problemy, możemy użyć właściwości klienta eksportu znanej jako net.sf.jasperreports.export.character.encoding . Ta niestandardowa właściwość eksportu ma wartość domyślną UTF-8 i jest obecna w JasperReports.

Ta wartość domyślna jest ustawiona w pliku default.jasperreports.properties . Aby uzyskać bardziej szczegółowe opcje w czasie eksportu, dostępny jest również parametr eksportu CHARACTER_ENCODING.

Przykład

Aby zademonstrować użycie obsługi Unicode w Jasperreports, napiszmy nowy szablon raportu (jasper_report_template.jrxml). Save it to C:\tools\jasperreports-5.0.1\testinformator. Tutaj wyświetlimy tekst w różnych językach przy użyciu znaków Unicode (\ uXXXX). Dowolny znak zakodowany w UTF-8 może być reprezentowany tylko za pomocą 4-cyfrowego kodu szesnastkowego. Na przykład grecką literę Γ można zapisać jako \ u0393. W przypadku napotkania takiej notacji silnik żąda odpowiedniej reprezentacji znaku w zestawie znaków i tylko ten konkretny znak zostanie wydrukowany. Zawartość JRXML jest jak poniżej -

<?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>

W powyższym pliku widzimy obecność kodowania UTF-8. Również zlokalizowane fragmenty tekstu Unicode są przechowywane w parametrach dokumentu.

Kod java do wypełnienia i wygenerowania raportu jest jak poniżej. Zapiszmy ten plikJasperUnicodeReportFill.java do katalogu 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();
      }

   }
}

Tutaj używamy instancji JREmptyDataSource podczas wypełniania raportów, aby symulować źródło danych z jednym rekordem, ale wszystkie pola w tym pojedynczym rekordzie są puste .

Generowanie raportów

Skompilujemy i uruchomimy powyższy plik przy użyciu naszego zwykłego procesu budowania ANT. Zawartość pliku build.xml (zapisanego w katalogu C: \ tools \ jasperreports-5.0.1 \ test) jest następująca.

Plik importu - baseBuild.xml jest pobierany z rozdziału Konfiguracja środowiska i powinien być umieszczony w tym samym katalogu co 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>

Następnie otwórzmy okno wiersza poleceń i przejdźmy do katalogu, w którym znajduje się plik build.xml. Na koniec wykonaj polecenieant -Dmain-class=com.tutorialspoint.JasperUnicodeReportFill (viewFullReport jest domyślnym celem) w następujący sposób -

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

W wyniku powyższej kompilacji otworzy się okno JasperViewer, jak pokazano na poniższym ekranie -

Tutaj widzimy, że wyświetlany tekst jest w różnych językach. Widzimy również, że języki są zgrupowane razem na tej samej stronie, a także zmieszane w tym samym elemencie tekstowym.