JAVA读取RTF文档

女生的网名这么多〃 提交于 2019-12-08 15:12:00

RTF,全称是“富文本格式“,它便于在应用程序之间轻松的转换文本和图形。想了解RTF文件基本格式及相关可以点击这里

需要注意的是,在RTF文件中,对于占双字节的中文,都是用单字节的ASCII字符表示,例如文本“宋体ABC”应该表示为:\'cb\'ce\'cc\'e5ABC,

这种编码我们称之为“汉字机内码”,简称“内码”。把国标码的汉字代码中的区码与位码分别换算为16进制数,然后再分别加上十六进制数80,

即为该汉字的机内码。由于内码的编码方式,所以我们最好在读取RTF文件流的时候将两个字节合并成单个16进制字符,然后在write的时候

将其转换成unicode编码,才能显示成中文字符。

以下有示例代码仅供参考:

注意:这里只解析中文字符,对于单字节字符由于不是内码方式编码,所以是读取不到的)

package jj.RTF;
/**
 * 解析RTF文件
 * @author jj
 *
 */
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;

public class TestParseRTF {
	private static String filePath = "E:/testRTF.rtf";
	private static List<Character> buffer;
	public static void main(String[] args) throws Exception {
		readFile();
		parseRTF();
		//printIns();
	}
	
	/**
	 * 将内码转成16进制编码
	 * @throws IOException 
	 */
	public static void readFile() throws IOException {
		InputStream in = new FileInputStream(new File(filePath));
		int ch;
		buffer = new ArrayList<Character>();
		while((ch=in.read()) > 0) {
			if (ch == '\\') {
				ch = in.read();
			}//这种形式的都是双字节字符
			if (ch == '\''){
				char ch1 = (char) in.read();
				char ch2 = (char) in.read();
				// ']'或'^'
				if (ch1 == '9' && (ch2 == '3' || ch2 == '4')) {
					
				}
				//将两个十进制的数,合并转变成16进制
				/**98--11
				 * 99--12
				 * 合成11*16+12=188
				 */
				ch = Character.digit(ch1,16)*16 + Character.digit(ch2,16);
				buffer.add((char) ch);
			}
		}
	}
	
	
	/**
	 * 将16进制编码字符转成unicode编码的字符,并显示成中文字符串
	 * @throws UnsupportedEncodingException 
	 */
	public static void parseRTF() throws UnsupportedEncodingException {
		byte[]byteArr = new byte[buffer.size()];
		for(int i = 0;i < buffer.size();i++) {
			char ch = buffer.get(i);
			if (ch < 0x80) {
				byteArr[i] = (byte)ch;
			}  else if (ch < '\u00FF') {
				char a = toHex(ch / 16);
				char b = toHex(ch % 16);
				String t = "" + a + b;
				int hb = Integer.parseInt(t, 16);
				byteArr[i] = (byte)hb;
			}
		}
		System.out.println(new String(byteArr));
	}
	
	public static char toHex(int ch) {
		if (ch < 10) {
			return (char) ('0' + ch);
		} else {
			return (char) ('a' + ch - 10);
		}
	}
	
	// 16进制字符转成中文字符
	public static String hexToStringGBK(String s) {
		byte[] baKeyword = new byte[s.length() / 2];
		for (int i = 0; i < baKeyword.length; i++) {
			try {
				baKeyword[i] = (byte) (0xff & Integer.parseInt(s.substring(i * 2, i * 2 + 2), 16));
			} catch (Exception e) {
				e.printStackTrace();
				return "";
			}
		}
		try {
			s = new String(baKeyword, "GBK");// UTF-16le:Not
		} catch (Exception e1) {
			e1.printStackTrace();
			return "";
		}
		return s;
	}//查看RTF文件原始编码字符
	public static void printIns() throws IOException {
		InputStream in = new FileInputStream(new File(filePath));
		int ch;
		while((ch=in.read()) > 0) {
			System.out.print((char)ch);
		}
	}
}

程序运行结果:

宋体宋体}¨·ˇˉā薄谩ⅰ!ā怠贰埂弧俊场剑。ⅲВ海唬浚荩啵閧·‘“〈《「『【〔〖(.[{£¥这是一首简单的小情歌

(注:“这是一首简单的小情歌”是rtf文本内容)

推荐这里的文件流使用PushbackInputStream,即回退输入流(虽然我没用。。),这种流允许程序可以读取到特定字符。

想了解可点击回退输入流

至于完成一个RTF解析器,还是挺复杂的。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!