RTF转HTML,HTML转TXT(Java版)

想要做一个RTF转换TXT的代码,找了一圈,好不容易找了个折中的方法,先转HTML,然后提取HTML中的纯文本部分,下面把整个方法介绍一下。

一、第三方开发包

先简单介绍一下RTF格式相关的内容,摘自百度百科:

作为微软公司的标准文件,早期外间需要数十美元向微软付款,才能购买一本薄薄的RTF标准文件。不过随着采用RTF格式标准的软件愈来愈多,RTF格式也愈来愈普遍,微软公司就把标准文件公开,放在网上供开发者下载。现时可供下载的各个RTF版本标准文件如下:
  RTF 1.9.1 specification (March 2008)
  RTF 1.8 specification (April 2004)
  RTF 1.6 specification (May 1999)
  RTF 1.5 specification (April 1997)
  RTF 1.3 and 1.5 specifications
  RTF 1.0 specification (June 1992)
  RTF格式是许多软件都能够识别的文件格式。比如Word、WPS Office、Excel等都可以打开RTF格式的文件,这说明这种格式是较为通用的。
  RTF是Rich Text Format的缩写,意即多文本格式。这是一种类似DOC格式(Word文档)的文件,有很好的兼容性,使用Windows“附件”中的“写字板”就能打开并进行编辑。使用“写字板”打开一个RTF格式文件时,将看到文件的内容;如果要查看RTF格式文件的源代码,只要使用“记事本”将它打开就行了。这就是说,你完全可以像编辑HTML文件一样,使用“记事本”来编辑RTF格式文件。

忘记怎么找到WebCAT了,可能找太多、太乱,当时的关键词也没记住,http://webcat.sourceforge.net/,JavaDoc可以从这里http://webcat.sourceforge.net/javadocs/访问。WebCAT是葡萄牙里斯本大学的一个XXX什么的开发的(WebCAT was developed at the XLDB group of the Department of Informatics of the Faculty of Sciences of the University of Lisbon in Portugal.),其中提供的RTF2HTML可以很方便地把RTF文件转换成HTML文件,而且速度也还可以。不过只是针对文本,不能保留图片等资源,有些遗憾,但是并不影响转TXT的目的。

二、RTF转HTML

new RTF2HTML().convertRTFToHTML(new File(filename)),方法convertRTFToHTML会返回一个转换成HTML格式的字符串。

三、HTML转TXT

当得到HTML格式文本后,就可以做HTML转TXT了,WebCAT里并不提供HTML转TXT,所以得自己实现。思路是先去除所有的HTML标记,之后将HTML转义字符还原成原始字符即可。对于去除HTML标记,用正则表达式还是比较方便的,另外就是如何还原HTML转义字符,自己写太麻烦而且还有可能无法覆盖所有情况,所以可以去网上找出现成的代码,这里找到的是一个叫做StringUtils的类,其中有一个unescapeHTML(String, int)方法就是用于反转HTML字符,如将“ ”转成空格。

四、查看系统信息

利用StringlistSystemInfo可以查看一些系统信息,具体实现请参考下面代码,对于打印出来的系统信息,有几项内容需要注意一下:

sun.jnu.encoding=Cp1252
file.encoding=UTF-8

file.encoding决定了Java做文件输出时的文件编码,sun.jnu.encoding表示读取文件时采用的什么样的字符编码。

五、开始测试

环境查看

C:/Workspace/php eclipse/Tester/bin>java -Dfile.encoding=UTF-8 -cp "C:/Workspace/eclipse/RTF/Document Parser;" Main -s
-- listing properties --
java.runtime.name=Java(TM) SE Runtime Environment
sun.boot.library.path=C:/Program Files/Java/jre6/bin
java.vm.version=16.3-b01
java.vm.vendor=Sun Microsystems Inc.
java.vendor.url=http://java.sun.com/
path.separator=;
java.vm.name=Java HotSpot(TM) Client VM
file.encoding.pkg=sun.io
user.country=US
sun.java.launcher=SUN_STANDARD
sun.os.patch.level=Service Pack 2
java.vm.specification.name=Java Virtual Machine Specification
user.dir=C:/Documents and Settings/Administrat...
java.runtime.version=1.6.0_20-b02
java.awt.graphicsenv=sun.awt.Win32GraphicsEnvironment
java.endorsed.dirs=C:/Program Files/Java/jre6/lib/endorsed
os.arch=x86
java.io.tmpdir=C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/
line.separator=

java.vm.specification.vendor=Sun Microsystems Inc.
user.variant=
os.name=Windows XP
sun.jnu.encoding=Cp1252
java.library.path=C:/WINDOWS/system32;.;C:/WINDOWS/Sun/...
java.specification.name=Java Platform API Specification
java.class.version=50.0
sun.management.compiler=HotSpot Client Compiler
os.version=5.1
user.home=C:/Documents and Settings/Administrator
user.timezone=
java.awt.printerjob=sun.awt.windows.WPrinterJob
file.encoding=UTF-8
java.specification.version=1.6
user.name=KNIGHTRCOM
java.class.path=C:/Documents and Settings/Administrat...
java.vm.specification.version=1.0
sun.arch.data.model=32
java.home=C:/Program Files/Java/jre6
java.specification.vendor=Sun Microsystems Inc.
user.language=en
awt.toolkit=sun.awt.windows.WToolkit
java.vm.info=mixed mode, sharing
java.version=1.6.0_20
java.ext.dirs=C:/Program Files/Java/jre6/lib/ext;C:...
sun.boot.class.path=C:/Program Files/Java/jre6/lib/resour...
java.vendor=Sun Microsystems Inc.
file.separator=/
java.vendor.url.bug=http://java.sun.com/cgi-bin/bugreport...
sun.cpu.endian=little
sun.io.unicode.encoding=UnicodeLittle
sun.desktop=windows
sun.cpu.isalist=pentium_pro+mmx pentium_pro pentium+m...

RTF转TXT。

C:/Workspace/php eclipse/Tester/bin>java -Dfile.encoding=UTF-8 -cp "C:/Workspace/eclipse/RTF/Document Parser;" Main

说明一下参数,-D后面可以让我们主动设置环境变量,所以我们可以设置下Java输出文件时所使用的编码;另外,我们在程序中使用了WebCAT提供的工具类,这些工具类位于解压后的Document Parser文件夹中,所以执行Main类时,需要将文件夹Document Parser放入环境变量中,以便程序可以顺利的找到相关类。

六、关于编码

如果字符编码设置不正确,很大可能会导致乱码现象。这个问题历来都是很棘手的,但是我们在开发过程中可以分析环境以及要读入的文件,然后得出一个正确的解决方案。程序首先是读入RTF然后转换成HTML,这个功能是WebCAT提供的,所以不用关注太多细节问题,但是在调试时发现,转换后的HTML是乱码的!其实这个跟Web开发中request.getParameter得到的结果是乱码的问题有相似之处,都是因为Java没有采用正确的文字编码读取输入字符造成的,在我的开发环境中,由于默认的编码格式是Cp1252(即sun.jnu.encoding的值),所以原本的GB2312就会错误的编码解读导致乱码。这时我们只需要把字符串重新按照正确编码读取一下就OK了。具体步骤是先用Cp1252编码把错误编码的String转成原始的byte,然后再用正确编码GB2312将byte转String还原原始文件的字符内容,代码请参考executeRTF2TXT中的newString(result.getBytes("Cp1252"),"GB2312");这句。

上面描述的是读取文本时产生的乱码现象,另外一个就是写文件的乱码,FileWriter.getEncoding()方法可以获取当前文件是以什么编码保存的,它的值依赖于file.encoding,所以在运行程序时添加一个-D选项设置这个值就可以了,如果有多个环境变量需要指定,可以多用几个-D。

七、源代码

为了删除无用空格,特地在程序中添加了一个StringUtils.trimThroughLines方法用于删除所有行中无效空格,其中正则的具体含义可以参考http://blog.csdn.net/rcom10002/archive/2009/08/19/4462284.aspx。程序的所有源码如下(展开查看):

import java.io.File; import java.io.FileWriter; import java.util.HashMap; import pt.tumba.parser.rtf.RTF2HTML; /** * Convert RTF to HTML, HTML to TXT * * @author KNIGHTRCOM(rcom10002@163.com) * */ public class Main { /** * @param args * @throws Exception */ public static void main(String[] args) throws Exception { if (args.length > 0) { if (args[0].equals("-s")) { listSystemInfo(); return; } else { System.out.println("usage: java Main [-s]"); return; } } System.out.println("你好"); // Generate rtf2.html executeRTF2TXT(); } /** * List the system info you may concern */ public static void listSystemInfo() { System.getProperties().list(System.out); } /** * Convert RTF to HTML * * @throws Exception */ private static void executeRTF2TXT() throws Exception { RTF2HTML rtf2html = new RTF2HTML(); String result = rtf2html .convertRTFToHTML(new File( "C:/Documents and Settings/Administrator/My Documents/Workspace/php eclipse/QAR Tool/questions/sample2.rtf")); // This step is important for rendering the text with proper encoding result = new String(result.getBytes("Cp1252"), "GB2312"); System.out.println(result); // Extract plain text from HTML result = result.replaceAll("(?i)<br.*?/?>", "<br />/n").replaceAll("<.+?>", ""); result = StringUtils.unescapeHTML(result, 0); // Write the result to the file FileWriter w = new FileWriter(new File("C:/rtf2.html")); System.out.println(w.getEncoding()); w.write(StringUtils.trimThroughLines(result)); w.close(); } } /** * http://www.rgagnon.com/javadetails/java-0307.html * */ class StringUtils { private StringUtils() { } private static HashMap<String, String> htmlEntities; static { htmlEntities = new HashMap<String, String>(); htmlEntities.put("<", "<"); htmlEntities.put(">", ">"); htmlEntities.put("&", "&"); htmlEntities.put(""", "/""); htmlEntities.put("à", "à"); htmlEntities.put("À", "À"); htmlEntities.put("â", "â"); htmlEntities.put("ä", "ä"); htmlEntities.put("Ä", "Ä"); htmlEntities.put("Â", "Â"); htmlEntities.put("å", "å"); htmlEntities.put("Å", "Å"); htmlEntities.put("æ", "æ"); htmlEntities.put("Æ", "Æ"); htmlEntities.put("ç", "ç"); htmlEntities.put("Ç", "Ç"); htmlEntities.put("é", "é"); htmlEntities.put("É", "É"); htmlEntities.put("è", "è"); htmlEntities.put("È", "È"); htmlEntities.put("ê", "ê"); htmlEntities.put("Ê", "Ê"); htmlEntities.put("ë", "ë"); htmlEntities.put("Ë", "Ë"); htmlEntities.put("ï", "ï"); htmlEntities.put("Ï", "Ï"); htmlEntities.put("ô", "ô"); htmlEntities.put("Ô", "Ô"); htmlEntities.put("ö", "ö"); htmlEntities.put("Ö", "Ö"); htmlEntities.put("ø", "ø"); htmlEntities.put("Ø", "Ø"); htmlEntities.put("ß", "ß"); htmlEntities.put("ù", "ù"); htmlEntities.put("Ù", "Ù"); htmlEntities.put("û", "û"); htmlEntities.put("Û", "Û"); htmlEntities.put("ü", "ü"); htmlEntities.put("Ü", "Ü"); htmlEntities.put("", " "); htmlEntities.put("©", "/u00a9"); htmlEntities.put("®", "/u00ae"); htmlEntities.put("€", "/u20a0"); } public static final String unescapeHTML(String source, int start) { int i, j; i = source.indexOf("&", start); if (i > -1) { j = source.indexOf(";", i); if (j > i) { String entityToLookFor = source.substring(i, j + 1); String value = (String) htmlEntities.get(entityToLookFor); if (value != null) { source = new StringBuffer().append( source.substring(0, i)).append(value).append( source.substring(j + 1)).toString(); return unescapeHTML(source, i + 1); // recursive call } } } return source; } /** * Remove heading and tailing space or tab of all lines * * @param source * @return */ public static final String trimThroughLines(String source) { return source.replaceAll("(?ms)^//s+|//s+$", ""); } public static void main(String args[]) throws Exception { // to see accented character to the console java.io.PrintStream ps = new java.io.PrintStream(System.out, true, "Cp850"); String test = "© 2007 Réal Gagnon <www.rgagnon.com>"; ps.println(test + "/n-->/n" + unescapeHTML(test, 0)); /* * output : © 2007 Réal Gagnon <www.rgagnon.com> * --> © 2007 Réal Gagnon <www.rgagnon.com> */ } }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值