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解析器,还是挺复杂的。
来源:CSDN
作者:jiangzhongwei_
链接:https://blog.csdn.net/jiangzhongwei_/article/details/52138268