转自: https://blog.csdn.net/pigdreams/article/details/601
相信有同学已经发现了,当预览生成为PDF时,会发现一个非常严重的问题,那就是只显示英文与数字,中文完全无法显示。如下图。
选择用PDF预览,会打开电脑上安装的PDF查看软件。
生成的PDF文件中,所有中文都无法显示,这是模板预览生成的PDF文件,如果用JAVA工程生成相信也是一样无法看到中文,这跟我们想要的效果明显不符。
解决Jaspersoft studio生成PDF预览无法查看中文的问题
我们的模板设计软件Jaspersoft studio是可以选择字体,如果我们选择一个中文字体,会不会可以在预览中看到中文呢?注意,这里只是针对于Jaspersoft studio的预览查看,并不适用于Java工程中代码生成PDF无法显示中文问题。
我们选择一个中文字体试试
很奇怪的地方是上面的六个字体样式与下面的字体样式有一个明显的分隔线,它们有什么不同吗?这就是我们要讲解的重点。
上面的六个字体样式明显没有中文字体,那我们只好选择下面的字体了。
将语文的字体设为微软雅黑,再看看预览是否有效果。
源码里的描述如下:
生成预览
语文依然没有显示,这个方法无效果。
fonts字体包的作用
在工程目录,有三个自动导入的项目包,如下图,一个是Java JRE,其余两个都是Jasperreport工程相差的包
我们的重点是JasperReports Library里面的fonts字体包,展开该Jar包。
里面放置了许多.ttf字体文体,而这些字体的名称与模板的选择字体框上方的字体基本一致。
由此可以大胆猜测,这个fonts包里放的字体就是模板实际用于生成文件所用的字体,我们在模板里选择的字体在源码中可以看到是一个标签”fonts-name=dejavvu..”,当Jasperreports解析模板文件时,会根据这个字体的名字然后去fonts字体包中查找对应的字体,如果用就使用该字体,如果没有就使用一个默认的字体。
在Jaspersoft studio中导入中文字体.ttf文件
我们可以在studio中导入一个中文字体,来实现pdf预览可查看中文的效果。
1.打开选项设置,preferences
2.选中Fonts选项
3.点击Add,添加字体
4.设置字体名字
名字可以随便取,然后选取电脑上下载好的字体文件ttf格式的。
最重要的一步,选择PDF ENconding一定要选择这个选项Identity-H,要不然依然是显示空白的中文。至于为什么选择这个,是因为我在上一步选择的是从文件夹里导入字体文件,然后将电脑系统自带的Font文件夹给选中,结果是将所有几乎上百个是.tff格式的字体都给导进去了。
选择文件夹导入,如果是ttf的软件会自动分析pdf encoding,所以可以从这个方法知道华文宋体的编码方式。
为了显示方便,所以我删掉了没用的字体,只留下了华文宋体。
现在来看看预览效果如何,现在选取字体的时候华文宋体出现在了上面的六个默认字体中了。
只有设置了华文字体的语文才正常地显示,说明PDF要想显示中文需要设置中文格式的字体。
IText的补充包ITextAsian并不能解决无法显示中文的问题
一开始我遇到这个问题时,网上搜的方法几乎都是将ItextAsian导入至工程中,事实上这并没有什么效果。虽然我们的Pdf是用Itext生成了,但是在Jasperreports 6.3.1里面加入补充包不起作用。
现在我们来试验一下IText是否起作用,模板是最开始的需要传入参数的那个,我将语文数学设为华文宋体。
我的Jar包中是有这个ItextAsian的。
运用代码生成Pdf文档。
package test;
import java.util.HashMap;
import net.sf.jasperreports.engine.JREmptyDataSource;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperExportManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
public class JasperCreatePdf {
public static void main(String[] args) {
//1.设定模板二进制文件路径,一定要可以通过该路径找到该文件
String reportPath="./src/JasperSample.jasper";
//2.设定报表的外部参数,map集合,这里要注意map的key值一定要与模板里Parameters的名字一致
HashMap<String,Object> map=new HashMap<>();
map.put("name", "王小明");
map.put("id", "2017022301");
map.put("rank", "32");
map.put("yuwen", "81");
map.put("shuxue", "102");
map.put("english", "123");
map.put("shengwu", "67");
map.put("wuli", "75");
map.put("huaxue", "86");
map.put("rankone", "21");
try {
//3.通过JasperFillManager工具进行填充报表,填充成功后会生成一个JasperPring文件,该文件用于输出
JasperPrint jasperPrint=JasperFillManager.fillReport(reportPath, map,new JREmptyDataSource());
//4.设定目标文件输出的路径
String desFilePath="./src/JasperPdfDemoTest.pdf";
//5.通过JasperExportManager管理工具进行报表输出文档,此外设定为输出PDF文件
JasperExportManager.exportReportToPdfFile(jasperPrint,desFilePath);
} catch (JRException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
刷新工程,可以看到生成的Pdf文档,依然是中文一片空白,所以ITextAsian的方案无用。
运用Fonts Jar包解决Pdf无法显示中文问题
当初在网上找过许多方法,最后找到一个靠谱的,它的解决方案就是将我们的中文字体包加入到Fonts这个Jar包中,然后导入工程中,这样就可以一劳永逸解决字体的问题,至于ITextAsian则是因为从Jasperreports6.0开始就不支持这种方法解决中文问题。下面来为大家介绍如何将中文字体加入到Fonts字体包中。
1.打开下载的Project包里面的demo下的fonts文件夹
里面有一个net包,一直往下点,直到看到下面这个xml文件
2.用程序员软件打开fonts.xml这个文件
这个文件就是用以声明字体文件的,从它的结构很容易就可以看出一个命名字体的标签fontFamilly,下面的子标签是normal,bold,italic即正常,粗体,斜体对应的字体文件,还有pdfEncoding标签,exportFonts标签,是不是与上面我们导入字体的设置差不多。
下面的文件我只保留了一个字体说明,省去了自带的两个字体,以便于说明。
<?xml version="1.0" encoding="UTF-8"?>
<fontFamilies>
<fontFamily name="DejaVu Sans">
<normal>net/sf/jasperreports/fonts/dejavu/DejaVuSans.ttf</normal>
<bold>net/sf/jasperreports/fonts/dejavu/DejaVuSans-Bold.ttf</bold>
<italic>net/sf/jasperreports/fonts/dejavu/DejaVuSans-Oblique.ttf</italic>
<boldItalic>net/sf/jasperreports/fonts/dejavu/DejaVuSans-BoldOblique.ttf</boldItalic>
<pdfEncoding>Identity-H</pdfEncoding>
<pdfEmbedded>true</pdfEmbedded>
<exportFonts>
<export key="net.sf.jasperreports.html">'DejaVu Sans', Arial, Helvetica, sans-serif</export>
<export key="net.sf.jasperreports.xhtml">'DejaVu Sans', Arial, Helvetica, sans-serif</export>
</exportFonts>
<!--
<locales>
<locale>en_US</locale>
<locale>de_DE</locale>
</locales>
-->
</fontFamily>
<!--
Mapping Java logical fonts, for the sake of HTML export only.
-->
<fontFamily name="SansSerif">
<exportFonts>
<export key="net.sf.jasperreports.html">'DejaVu Sans', Arial, Helvetica, sans-serif</export>
<export key="net.sf.jasperreports.xhtml">'DejaVu Sans', Arial, Helvetica, sans-serif</export>
</exportFonts>
</fontFamily>
</fontFamilies>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
3.打开net/sf/jasperreports/fonts/dejavu这个文件夹
从上面的标签里面可以看出,我们的字体文件就放在这个文件夹里面,现在我们来看看里面有什么。
里面全都是.ttf文件,与标签里的内容一一对应。
4.复制一个中文字体文件至net/sf/jasperreports/fonts/dejavu中
我们将一个中文字体复制至该文件夹,接下来的事情就很简单了,我们只需复制xml里面的声明标签,改下名字,就可以配置好中文字体了。
5.在fonts.xml里配置华文宋体信息
其实这一步很简单,我们只需要参照上面的字体信息就可以配置好我们的自定义字体了,但是要注意名字一定要与模板里的选用的字体名字一致,否则是找不到该字体的。
<?xml version="1.0" encoding="UTF-8"?>
<fontFamilies>
<fontFamily name="DejaVu Sans">
<normal>net/sf/jasperreports/fonts/dejavu/DejaVuSans.ttf</normal>
<bold>net/sf/jasperreports/fonts/dejavu/DejaVuSans-Bold.ttf</bold>
<italic>net/sf/jasperreports/fonts/dejavu/DejaVuSans-Oblique.ttf</italic>
<boldItalic>net/sf/jasperreports/fonts/dejavu/DejaVuSans-BoldOblique.ttf</boldItalic>
<pdfEncoding>Identity-H</pdfEncoding>
<pdfEmbedded>true</pdfEmbedded>
<exportFonts>
<export key="net.sf.jasperreports.html">'DejaVu Sans', Arial, Helvetica, sans-serif</export>
<export key="net.sf.jasperreports.xhtml">'DejaVu Sans', Arial, Helvetica, sans-serif</export>
</exportFonts>
<!--
<locales>
<locale>en_US</locale>
<locale>de_DE</locale>
</locales>
-->
</fontFamily>
<fontFamily name="华文宋体">
<normal>net/sf/jasperreports/fonts/dejavu/STSONG.TTF</normal>
<bold>net/sf/jasperreports/fonts/dejavu/STSONG.TTF</bold>
<italic>net/sf/jasperreports/fonts/dejavu/STSONG.TTF</italic>
<boldItalic>net/sf/jasperreports/fonts/dejavu/STSONG.TTF</boldItalic>
<pdfEncoding>Identity-H</pdfEncoding>
<pdfEmbedded>true</pdfEmbedded>
<exportFonts>
<export key="net.sf.jasperreports.html">'华文宋体', Arial, Helvetica, sans-serif</export>
<export key="net.sf.jasperreports.xhtml">'华文宋体', Arial, Helvetica, sans-serif</export>
</exportFonts>
<!--
<locales>
<locale>en_US</locale>
<locale>de_DE</locale>
</locales>
-->
</fontFamily>
<!--
Mapping Java logical fonts, for the sake of HTML export only.
-->
<fontFamily name="SansSerif">
<exportFonts>
<export key="net.sf.jasperreports.html">'DejaVu Sans', Arial, Helvetica, sans-serif</export>
<export key="net.sf.jasperreports.xhtml">'DejaVu Sans', Arial, Helvetica, sans-serif</export>
</exportFonts>
</fontFamily>
<fontFamily name="华文宋体">
<exportFonts>
<export key="net.sf.jasperreports.html">'华文宋体', Arial, Helvetica, sans-serif</export>
<export key="net.sf.jasperreports.xhtml">'华文宋体', Arial, Helvetica, sans-serif</export>
</exportFonts>
</fontFamily>
</fontFamilies>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
6.生成一个fonts.Jar
这一步是比较关键的,我们只需将刚才配置好的xml文件与放置字体文件的文件夹打包成一个Jar包,注意一定要出到最外面的fonts文件夹中,因为我们的Jar包需要一个完整的路径包。
下面我们用jar命令来生成一个Jar包
1.回到fonts文件夹中,在地址栏中输入cmd后回车
2.在dos中输入下面命令
jar cvf fonts.jar *
- 1
这句话的意思是将当前目录下的所有文件输出到名为fonts.jar的文件上。
3.找到生成的jar包
7.将生成fonts.jar导入工程中,替代掉原有的fonts.jar包
导入新的fonts.jar后,运行java工程,查看pdf文件。
8.大功造成,Pdf文件无法显示中文问题完美解决。
最后提供该章生成的包含华文宋体的fonts.jar包。
下载传送门