统一码支持


在 JasperReports 中,处理文本需要一些专用工具来处理字符表示和文本格式属性。任何文本都可以被视为具有特定表示结构的字符序列。文本外观由布局(和段落)和字体设置组成。但是,虽然在大多数情况下,文本布局保持不变,但在不同区域设置中运行报表时,字体设置可能会发生变化。

我们知道不同的语言对于特定的字符表示需要不同的字符集。因此,处理文本就意味着处理字体。不过,有关如何在 JasperReports 中使用字体的详细讨论可在“报表字体”一章中找到。

给定报告中文本内容的主要特征之一是可以将其国际化。这意味着,我们可以在不同的本地化环境中使用不同的语言和其他本地化设置运行报告,而无需进行任何硬编码修改。当报表想要国际化时,字符编码是一个重要的功能。

字符编码

字符是传达有意义信息的最小书写单位。这是一个抽象的概念,角色没有视觉外观。“大写拉丁语 A”与“小写拉丁语 a”以及“大写西里尔字母 A”和“大写希腊字母 Alpha”是不同的字符。

字符的视觉表示称为字形。一组特定的字形称为字体。“大写拉丁语 A”、“大写西里尔字母 A”和“大写希腊字母”可能具有相同的字形,但它们是不同的字符。同时,“大写拉丁语 A”的字形在 Times New Roman、Gill Sans 和 Poetica chanchery italic 中看起来可能非常不同,但它们仍然代表相同的字符。

可用字符集称为字符库。给定字符在指令集内的位置(索引)称为其代码位置或代码点。用数字表示给定指令集内的代码点的方法称为字符编码

编码通常以八位位组表示。八位位组是一组八个二进制数字,即八个 1 和 0。八位字节可以表示 0 到 255 之间或 0x00 到 0xFF 之间的数字范围,以使用十六进制表示法。

统一码

Unicode 是一个字符库,包含世界上语言中使用的大部分字符。它可以容纳数百万个字符,并且已经包含数十万个字符。Unicode 被划分为 64K 字符的“平面”。在大多数情况下唯一使用的是第一个平面,称为基本多语言平面,或 BMP。

推荐使用 UTF-8 编码。它使用可变数量的八位位组来表示不同的字符。

在 JRXML 文件中,编码属性在标头中指定。它在报告编译时用于解码 XML 内容。例如,如果报告仅包含法语单词和 ç、é、â 等字符,则 ISO-8859-1(又名 Latin-1)编码就足够了 -

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

如上所示,理想情况下我们可以选择适合最小字符集的编码,它可以正确表示文档中的所有字符。但对于多语言文档(即包含多种语言拼写的单词的文档),应该选择适合最小字符集的编码,能够正确表示文档中的所有字符,即使它们属于不同的语言。能够处理多语言文档的字符编码之一是UTF-8,JasperReports 用作默认编码值。

在国际化过程中,文本通常保存在资源包文件中,而不是保存在文档中。因此,在某些情况下,JRXML 本身看起来完全与 ASCII 兼容,但运行时生成的报告确实包含无法用 ASCII 读取的文本。因此,对于某种类型的文档导出格式(例如 CSV、HTML、XHTML、XML 和文本),还必须知道生成的文档的编码。不同的语言有不同的字符编码支持。因此每次我们都需要在本地化环境中运行报告。此外,我们必须知道哪种字符编码最适合生成的文档语言。在这种情况下,JRXML 文件本身中定义的编码属性可能不再有用。

为了解决此类问题,我们可以使用名为net.sf.jasperreports.export.character.encoding的导出客户属性。此导出自定义属性默认为 UTF-8,并且存在于 JasperReports 中。

该默认值在default.jasperreports.properties文件中设置。对于导出时的更具体选项,还可以使用 CHARACTER_ENCODING 导出参数。

例子

为了演示在 Jasperreports 中使用 unicode 支持,让我们编写新的报告模板 (jasper_report_template.jrxml)。将其保存到 C:\tools\jasperreports-5.0.1\test目录。在这里,我们将使用 Unicode 字符 (\uXXXX) 显示不同语言的文本。任何使用 UTF-8 编码的字符都可以仅使用其 4 位十六进制代码来表示。例如,希腊字母 Г 可以写成 \u0393。当遇到这样的符号时,引擎会在字符集中调用适当的字符表示形式,并且只有该特定字符才会被打印出来。JRXML 的内容如下:

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

在上面的文件中,我们可以看到UTF-8编码的存在。此外,本地化的 Unicode 文本片段也存储在文档参数中。

填写和生成报告的java代码如下。让我们将此文件JasperUnicodeReportFill.java保存到 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();
      }

   }
}

这里,我们在填充报表时使用JREmptyDataSource的实例来模拟其中包含一条记录的数据源,但该单条记录中的所有字段均为null

报告生成

我们将使用常规 ANT 构建过程来编译并执行上述文件。文件 build.xml(保存在目录 C:\tools\jasperreports-5.0.1\test 下)的内容如下。

导入文件 - baseBuild.xml 从“环境设置”一章中选取,应放置在与 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>

接下来,我们打开命令行窗口并进入build.xml所在的目录。最后,执行命令ant -Dmain-class=com.tutorialspoint.JasperUnicodeReportFill(viewFullReport 是默认目标),如下所示 -

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

作为上述编译的结果,JasperViewer 窗口将打开,如下面给出的屏幕所示 -

Jasper 报告 Unicode 示例

在这里,我们可以看到显示的文本是不同语言的。我们还看到,这些语言在同一页面上分组在一起,并且也混合到同一文本元素中。