|
|
1.背景 2.出现的问题 3.问题的解决 4.总结
1.背景 在JSP中如何应用iText生成中文PDF文件,问题一般出现在两个方面,其一是如何利用iText在JSP中生成PDF文件,其二就是中文问题。第一个问题在拙文《如何利用iText在JSP中生成PDF报表》中已经有所阐述,相信各位朋友在作类似开发的时候此文会起到一些作用。在该文后面的评论中,有网友提出了中文问题,我才意识到另写一篇文章的必要性。虽然人所共知Java的中文问题都源自编码,但是碰到具体问题的时候,明白原理与解决问题之间往往还有一些距离。希望本文于诸君有所裨益,正在做类似开发的朋友可以藉此快速解决类似的问题;而不在做类似开发的朋友可以将本文所提到的问题当作Java中文问题的一个实例,举一隅而以三隅反,更深刻地理解Java中文问题产生的缘由。 本文是鄙人想阐述的iText中文问题的第二部分——JSP中可能出现的中文问题。第一部分是关于普通的Java Application中出现的中文问题,已经写就。这两篇文章将我曾经做过的一些最终解决了我所面临的问题的摸索写出,与君共享——于君有益,则我之幸。
2.出现的问题 我们先来回顾一下在JSP中生成PDF文件的程序: <%@ page import="java.io.*,java.awt.Color,com.lowagie.text.*,com.lowagie.text.pdf.*" errorPage="error.jsp" %> <% response.setContentType( "application/pdf"); // step 1: creation of a document-object Document document = new Document(); // step 2: // we create a writer that listens to the document // and directs a PDF-stream to a temporary buffer ByteArrayOutputStream buffer = new ByteArrayOutputStream(); PdfWriter writer=PdfWriter.getInstance( document, buffer ); // step 3: we open the document document.open(); // step 4: we add a paragraph to the document document.add(new Paragraph(“HelloWorld!”)); // step 5: we close the document document.close(); // step 6: we output the writer as bytes to the response output DataOutput output = new DataOutputStream( response.getOutputStream() ); byte[] bytes = buffer.toByteArray(); response.setContentLength(bytes.length); for( int i = 0; i < bytes.length; i++ ) { output.writeByte( bytes[i] ); } %> 我们已经知道,在服务器正常运行的情况下,浏览器中访问该JSP页,会调用AcrobatReader应用程序,打开一个PDF文件。在这个PDF文件中,我们写入了一行英文:HelloWorld!。 我们自然希望在自己生成的PDF文件中随心所欲地添加自己国家的语言文字,第一个反应当然是直接将中文在程序中做成字符串,替换掉原先的HelloWorld!: // step 4: we add a paragraph to the document document.add(new Paragraph(“大家辛苦了!”)); 我们懊丧地在PDF文件中看见了一行穷形尽相的乱码。
3.问题的解决 我们在Java Application中已经解决了iText的中文问题,我们自然希望同样的办法可以在此处继续发挥作用。 假设我们已经正确安置了iText的另一个包iTextAsian.jar,我们在程序中做出一些修改: <%@ page import="java.io.*,java.awt.Color,com.lowagie.text.*,com.lowagie.text.pdf.*, com.lowagie.text.pdf.BaseFont;" errorPage="error.jsp" %> <% ……… BaseFont bfComic = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED); Font font = new Font(bfComic, 12, Font.NORMAL); String str=new String("大家辛苦了!"); document.add(new Paragraph(str,font)); ……… %> 我们已经知道,如果在Application中作出以上的修改,我们可以如愿以偿在PDF文件中得到我们所需要的中文。所以我们现在就可以在IE中满怀希望地访问修改后的JSP文件了。 我们得到了什么?是一堆搔首弄姿的符号!这说明Application中的解决之道照搬过来是行不通的。我们必须寻求别的方法。 我们希望可以从教程上找到解决的办法:www.lowagie.com/iText/tutorial/ch09.html,到这里来碰碰运气吧。于是我们可以知道,iText还支持TrueType的字体,当然,前提条件是我们的操作系统下面有相应的.ttf文件。 于是我们在程序中又作出如下的改变: <% ………….. BaseFont bfComic = BaseFont.createFont("c:\\winnt\\fonts\\msgothic.ttc,0", BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED); Font font = new Font(bfComic, 20); String str=new String("大家辛苦了!"); document.add(new Paragraph(str,font)); ……… %> 这些修改是可以根据从教程得到的启示来完成的,至于这里为什么要选用msgothic字体,教程并没有告诉我们,我们只能是通过别的渠道得来了。这上面所花费的时间按下不表。 鉴于前面的教训,我们只能对上述修改能否奏效抱定有限度的信心。让我们在IE中访问一下吧。打开PDF文件又看见了熟悉的乱码。至少这次我们是有心理准备的。 我们在继续沮丧的同时,有理由对在程序中直接将中文做成字符串的方法表示一下一定程度的怀疑。除非我们的身边有一个无所不知的智者,否则我们顺理成章地开始在网络上搜索,以期在浩如烟海的资料中寻求到我们的所需。 如下的一句话使我们的眼前一亮,这种感觉并无任何夸张的成分在里面:“string其实核心是char[],然而要把byte转化成string,必须经过编码。string.length()其实就是char数组的长度,如果使用不同的编码,很可能会错分,造成散字和乱码。” 我们忍不住扪心自问,我们在PDF加入中文,用的是什么编码?gb2312,GBK…都可以;然而我们在程序中所做的中文字符串,用的是什么编码呢?我们根本就没有考虑过这个问题!如果我们连自己做的字符串是什么编码都不知道,那么我们凭什么要求PDF中输出gb2312或者GBK的字符呢? 我们在程序中做成的中文字符串的编码,跟程序所用的编辑环境有关,我用的是EditPlus。编完程序以后保存文件的时候当然是可以选择合适编码的,一般我们不会去选择编码,EditPlus应该会有默认编码。这个默认编码是什么?EditPlus说:“默认编码。” 不要再去和编辑器本身去纠缠了,如果去寻求编辑器自带的帮助,我们确信能够得到我们所想知道的。但是知道了问题的缘由,余下的就变得十分简单了。 <% ………….. BaseFont bfComic = BaseFont.createFont("c:\\winnt\\fonts\\msgothic.ttc,0", BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED); Font font = new Font(bfComic, 20); String str=new String("同志们辛苦了!".getBytes("ISO8859_1"),"gb2312"); document.add(new Paragraph(str,font)); ……… %> 我们不管“同志们辛苦了!”这个字符串是什么编码,总之我们先把它存成标准字节码再说,然后再将这些字节码用gb2312编码做成相应的字符串。 运行一下吧,结果是什么?我们可以离开电脑去喝杯茶了。
4.总结 当初产生的问题比现在更混乱一些,因为涉及到了其他的因素。实际的任务是在日文版DreamweaverMX(内置Jrun服务器)环境下开发的,要求加入的是日文;当时的操作系统并非日文版Windows,仍然是中文的——只不过是将区域设置下由简体中文改成了日文。种种因素导致DreamweaverMX没有正确启动(DreamweaverMX启动的时候会根据操作系统的选择相应的编码,这一点很重要)。解决问题的过程是痛苦的,也是快乐的。 最后,谢谢阅读!
|
|