- - PR -
RTFファイルからテキストの内容のみを抽出する方法について
1
投稿者 | 投稿内容 |
---|---|
|
投稿日時: 2006-09-10 00:03
Webの画面からRTF(リッチテキストフォーマット形式)ファイルをアップロードし、
そのテキスト内容のみを取り出すプログラムをJavaで作成しようとしておりますが どうやって取ればいいかわからず難儀しています。 ちなみに javax.swing.text.rtf.RTFEditorKit が使えるかなと思って実験してみましたが 日本語がうまくとれません。 どなたか知恵を貸していただけないでしょうか。 よろしくお願いします。 |
|
投稿日時: 2006-10-02 15:43
完全な対応とは言えませんが、RTFで使われている日本語SJISの表現(ex \'fa\'96)を、\u65331 の表現に直してやると認識するようです。
下記のようなプログラムにて、一時ファイルに日本語の変換を行ったファイルを書き出し、そのファイルに対してRTFEditorKitを用いれば、日本語でも対応することができます。しかしながら、Wordで作成した作成したRTFだと読めない場合があったり、ワードパッド等でもうまく読めなくなるときがあります。 自作のプログラム等から書き出すような簡単なRTFの文法やRTFEditorKitから書き出す分には全く問題ないのですが。。 下記のソースのような方法以外に、他に読み込める方法があればご教授等おねがいします (一応、Apache FOP 等のライブラリ等は用いないで、というふうに回答が頂ければありがたいです。)。 --- readRTF.java import java.io.*; import java.util.*; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.Charset; import java.nio.charset.CharsetEncoder; import java.nio.charset.CharsetDecoder; import javax.swing.*; import javax.swing.text.*; import javax.swing.text.rtf.RTFEditorKit; /** * RTF の入出力に関するクラス */ public class readRTF { public readRTF() {} /** file から文字列の読み込み **/ private static StringBuffer readString(File file) { StringBuffer inb = new StringBuffer(); try { String str = ""; InputStreamReader fis = new InputStreamReader(new FileInputStream(file.getPath())); BufferedReader br = new BufferedReader(fis); while((str = br.readLine())!=null) { inb.append(str); inb.append("\n"); } br.close(); fis.close(); } catch(Exception ex) { ex.printStackTrace(); } return inb; } /** RTF内日本語文字列の変換 **/ private static File ConvertJapanese(File file) { File tmpfile = null; StringBuffer inb = readString(file); try { tmpfile = File.createTempFile("rtfRead-",".rtf"); tmpfile.deleteOnExit(); FileOutputStream fos = new FileOutputStream(tmpfile); // find sjis strings byte b[] = new byte[2]; for(int i=0;i<inb.length();i++){ if(i < inb.length()-8 && inb.substring(i,i+2).equals("\\\'")){ byte v1,v2; v1 = (byte)Character.digit((char)inb.substring(i+2,i+4).getBytes("SJIS")[0],16); v2 = (byte)Character.digit((char)inb.substring(i+3,i+4).getBytes("SJIS")[0],16); b[0] = (byte)(v1 * 16 + v2); if(inb.substring(i+4,i+5).equals(" ")) i++; if(inb.substring(i+4,i+6).equals("\\\'")) { v1 = (byte)Character.digit((char)inb.substring(i+6,i+7).getBytes("SJIS")[0],16); v2 = (byte)Character.digit((char)inb.substring(i+7,i+8).getBytes("SJIS")[0],16); b[1] = (byte)(v1 * 16 + v2); } else { v1 = v2 = 0; b[1] = 0; } fos.write(escapeJavaStyleString(new String(b,"SJIS"),true).getBytes("iso-8859-1")); i += 7; } else { fos.write(inb.charAt(i)); } } fos.close(); } catch(IOException ex) { ex.printStackTrace(); } catch(Exception ex) { ex.printStackTrace(); } return tmpfile; } /** 文字列から1行ずつ抽出**/ private static ArrayList splitLine(String s) { String body = s; body = body.replaceAll("\\Q\r\n","\n"); body = body.replaceAll("\\Q\r" ,"\n"); String[] ss = body.split("\\Q\n"); ArrayList v = new ArrayList(); for(int i=0;i<ss.length;i++) v.add(ss[i]); return v; } /** RTFファイルから1行ずつ抽出(word document not supported) **/ public static ArrayList readRTF(File file) { StringBuffer sb = new StringBuffer(); File tmpfile = ConvertJapanese(file); try { InputStream is = new FileInputStream(tmpfile); InputStreamReader isr = new InputStreamReader(is); RTFEditorKit rtf = new RTFEditorKit(); javax.swing.text.Document doc = rtf.createDefaultDocument(); rtf.read(isr,doc,0); if(doc.getLength() != 0){ sb.append(doc.getText(0,doc.getLength())); } else { JOptionPane.showMessageDialog(null,"対応しないRTFフォーマットです。"); return null; } } catch(Exception ex) { System.err.println("RTF read error: "+ex); return null; } return splitLine(new String(sb)); } private static String escapeJavaStyleString(String str, boolean escapeSingleQuote) throws IOException { StringBuffer sb = new StringBuffer(); if (str == null) { return ""; } int sz; sz = str.length(); if(sz > 1) { sb.append("{\\ul"); } else { sb.append("{"); } for (int i = 0; i < sz; i++) { char ch = str.charAt(i); int v = ch; // handle unicode if (ch > 0xfff) { sb.append("\\u" + v); } else if (ch > 0xff) { sb.append("\\u" + v); } else if (ch > 0x7f) { sb.append("\\u" + v); } else if (ch < 32) { switch (ch) { case '\b': sb.append('\\'); sb.append('b'); break; case '\n': sb.append('\\'); sb.append('n'); break; case '\t': sb.append('\\'); sb.append('t'); break; case '\f': sb.append('\\'); sb.append('f'); break; case '\r': sb.append('\\'); sb.append('r'); break; default : if (ch > 0xf) { sb.append("\\u" + v); } else { sb.append("\\u" + v); } break; } } else { switch (ch) { case '\'': if (escapeSingleQuote) { sb.append('\\'); } sb.append('\''); break; case '"': sb.append('\\'); sb.append('"'); break; case '\\': sb.append('\\'); sb.append('\\'); break; default : sb.append(ch); break; } } if(sz > 1) sb.append(" ? "); } if(sz > 1) { sb.append("\\ul0 }"); } else { sb.append("}"); } return new String(sb); } } [ メッセージ編集済み 編集者: gami 編集日時 2006-10-02 15:48 ] [ メッセージ編集済み 編集者: gami 編集日時 2006-10-02 15:57 ] |
|
投稿日時: 2006-10-04 21:20
自己レスです。
JavaのRTFEditorKitはUnicode表現の文字しか読みこまないようなので、RTF内の文字をすべてUnicode表現に直してあげれば読み込むことができるようになります。しかしながら、RTF内部には日本語だけではなくて、記号やその他の言語の表現が多々含まれることになりますので、日本語だけ考えれば良いというだけの話ではなさそうです。 RTF内にはフォントの情報が {\fNNN 〜 \fcharsetNNN;} のように含まれていますので、この情報を利用して、文字列をすべてUnicode表現に直していけばRTFEditorKitで読み込むことができるようになります。 以下、前回の例題を修正したものです。読みづらいかもしれませんが参考までに。 この例題なら、Word等で作成したRTFでもうまく読み取ることができます。 --- RTFio.java /** * RTFio: RTFファイルに対するテキストの入出力 * * @author gami * @version 1.0 */ import java.io.*; import java.util.*; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.Charset; import java.nio.charset.CharsetEncoder; import java.nio.charset.CharsetDecoder; import javax.swing.*; import javax.swing.text.*; import javax.swing.text.rtf.RTFEditorKit; /** * RTF の入出力に関するクラス */ public class RTFio { static CFontSet myFonts = new CFontSet(); /** RTFフォント情報 **/ private static class CFontSet { ArrayList fontNum,fontEnc; final String[] rtfFontset = new String[1500]; public CFontSet() { fontNum = new ArrayList(); fontEnc = new ArrayList(); for(int i=0;i<1500;i++) rtfFontset[i] = ""; rtfFontset[0] = "iso-8859-1";//0: ANSI rtfFontset[1] = "SJIS"; //1: Default rtfFontset[2] = "MacSymbol"; //2: Symbol rtfFontset[3] = ""; //3: Invalid rtfFontset[77] = "MacRoman"; //77: Mac rtfFontset[78] = "SJIS"; //Japanese rtfFontset[79] = "Cp950"; rtfFontset[80] = "EUC_KR"; rtfFontset[102] = "MS936"; rtfFontset[128] = "SJIS"; //128: Shift Jis rtfFontset[129] = "MS949"; //129: Hangul rtfFontset[130] = "x-Johab"; //130: Johab rtfFontset[134] = "MS936"; //134: GB2312 rtfFontset[136] = "Big5"; //136: Big5 rtfFontset[161] = "Cp1253"; //161: Greek rtfFontset[162] = "Cp1254"; //162: Turkish rtfFontset[163] = "Cp1258"; //163: Vietnamese rtfFontset[177] = "Cp1255"; //177: Hebrew rtfFontset[178] = "Cp1256"; //178: Arabic rtfFontset[179] = "Cp1256"; //179: Arabic Traditional rtfFontset[180] = "Cp864"; //180: Arabic user rtfFontset[181] = "Cp862"; //181: Hebrew user rtfFontset[186] = "Cp775"; //186: Baltic rtfFontset[204] = "Cp866"; //204: Russian rtfFontset[238] = "Cp1250"; //238: Eastern European rtfFontset[222] = "Cp874"; //222: Thai rtfFontset[254] = "Cp437"; //254: PC 437 rtfFontset[255] = "SJIS"; //255: OEM rtfFontset[256] = "MacRoman"; //256: rtfFontset[437] = "Cp437"; //437: United States IBM rtfFontset[708] = "Cp1256"; //708: Arabic (ASMO 708) rtfFontset[709] = "Cp1256"; //709: Arabic (ASMO 449+, BCON V4) rtfFontset[710] = "Cp1256"; //710: Arabic (transparent Arabic) rtfFontset[711] = "Cp1256"; //711: Arabic (Nafitha Enhanced) rtfFontset[720] = "Cp1256"; //720: Arabic (transparent ASMO) rtfFontset[819] = "Cp1250"; //819: Windows 3.1 (United States and Western Europe) rtfFontset[850] = "Cp850"; //850: IBM multilingual rtfFontset[852] = "Cp852"; //852: Eastern European rtfFontset[860] = "Cp860"; //860: Portuguese rtfFontset[862] = "Cp862"; //862: Hebrew rtfFontset[863] = "Cp863"; //863: French Canadian rtfFontset[864] = "Cp864"; //864: Arabic rtfFontset[865] = "Cp865"; //865: Norwegian rtfFontset[866] = "Cp866"; //866: Soviet Union rtfFontset[874] = "MS874"; //874: Thai rtfFontset[932] = "MS932"; //932: Japanese rtfFontset[936] = "MS936"; //936: Simplified Chinese rtfFontset[949] = "MS949"; //949: Korean rtfFontset[950] = "MS950"; //950: Traditional Chinese rtfFontset[1250] = "Cp1250"; //1250: Windows 3.1 (Eastern European) rtfFontset[1251] = "Cp1251"; //1251: Windows 3.1 (Cyrillic) rtfFontset[1252] = "Cp1252"; //1252: Western European rtfFontset[1253] = "Cp1253"; //1253: Greek rtfFontset[1254] = "Cp1254"; //1254: Turkish rtfFontset[1255] = "Cp1255"; //1255: Hebrew rtfFontset[1256] = "Cp1256"; //1256: Arabic rtfFontset[1257] = "Cp1257"; //1257: Baltic rtfFontset[1258] = "Cp1258"; //1258: Vietnamese rtfFontset[1361] = "x-Johab"; //1361: Johab } public String fontname(int n) { return rtfFontset[n]; } public void add(int n_font,int n_fcharset) { for(int i=0;i<fontNum.size();i++){ if(n_font == ((Integer)fontNum.get(i)).intValue()){ fontEnc.set(i,new Integer(n_fcharset)); return; } } fontNum.add(new Integer(n_font)); fontEnc.add(new Integer(n_fcharset)); } public String get(int n_font) { for(int i=0;i<fontNum.size();i++){ if(n_font == ((Integer)fontNum.get(i)).intValue()){ int cset = ((Integer)fontEnc.get(i)).intValue(); if(cset >= 0 && cset < 1500){ return rtfFontset[cset]; } return ""; } } return ""; } } /** ファイル内容をテキストとして取得 **/ private static StringBuffer readString(File file) { StringBuffer inb = new StringBuffer(); try { String str = ""; InputStreamReader fis = new InputStreamReader(new FileInputStream(file.getPath())); BufferedReader br = new BufferedReader(fis); while((str = br.readLine())!=null) { inb.append(str); inb.append("\n"); } br.close(); fis.close(); } catch(Exception ex) { ex.printStackTrace(); } return inb; } /** フォント情報の読み取り **/ private static void getRTFfontset(StringBuffer inb) { boolean ffont = false; int n_font = -1; for(int i=0;i<inb.length();i++){ if(ffont && inb.charAt(i) == ';'){ ffont = false; n_font = -1; continue; } // get font set if(!ffont && i < inb.length()-4 && inb.substring(i,i+2).equals("\\f")){ if(Character.isDigit(inb.substring(i+2,i+3).charAt(0))){ // get font number for(int fi=3;fi<6;fi++){ if(!Character.isDigit(inb.substring(i+fi,i+fi+1).charAt(0))){ try { n_font = Integer.valueOf(inb.substring(i+2,i+fi)).intValue(); break; } catch(java.lang.NumberFormatException e) { n_font = -1; break; } } } if(n_font >= 0){ ffont = true; } } } // get 'fcharset' of language type if(ffont && i < inb.length()-9 && inb.substring(i,i+9).equals("\\fcharset")){ int n_fcharset = -1; // get font number for(int fi=9;fi<13;fi++){ if(!Character.isDigit(inb.substring(i+fi,i+fi+1).charAt(0))){ try { n_fcharset = Integer.valueOf(inb.substring(i+9,i+fi)).intValue(); System.out.print("["+n_font+"] fcharset is "+n_fcharset+": "); if(n_fcharset >= 0){ myFonts.add(n_font,n_fcharset); System.out.println(myFonts.get(n_font)); } else { System.out.println(); } break; } catch(java.lang.NumberFormatException e) { n_font = -1; break; } } } } } } /** RTF文字列文字の変換(SJIS to UTF8) **/ private static File ConvertJapanese(File file) { File tmpfile = null; try { byte b1[] = new byte[1]; byte b2[] = new byte[2]; int skip = 0,n_font = -1,n_unicode = -1; String cset = ""; boolean breadrule = false; boolean bsymbol = false; boolean bbackslash = false; boolean breadfont = false; StringBuffer inb = readString(file); tmpfile = File.createTempFile("rtftmp",".rtf"); //tmpfile.deleteOnExit(); FileOutputStream fos = new FileOutputStream(tmpfile); // get fontset information getRTFfontset(inb); // read strings for(int i=0;i<inb.length();i++,skip=0){ // get font set if(i < inb.length()-4 && inb.substring(i,i+2).equals("\\f")){ if(Character.isDigit(inb.substring(i+2,i+3).charAt(0))){ // get font number for(int fi=3;fi<6;fi++){ if(!Character.isDigit(inb.substring(i+fi,i+fi+1).charAt(0))){ try { n_font = Integer.valueOf(inb.substring(i+2,i+fi)).intValue(); cset = myFonts.get(n_font); if(cset.equals("MacSymbol")){ bsymbol = true; } else { bsymbol = false; } break; } catch(java.lang.NumberFormatException e) { break; } } } } } // get 'fcharset' of language type if(i < inb.length()-9 && inb.substring(i,i+9).equals("\\fcharset")){ breadfont = true; } // get 'fchar' and 'lchar' rule if(i < inb.length()-9 && inb.substring(i,i+9).equals("\\*\\fchars")){ breadrule = true; } if(i < inb.length()-9 && inb.substring(i,i+9).equals("\\*\\lchars")){ breadrule = true; } // get unicode character if(i < inb.length()-4 && inb.substring(i,i+2).equals("\\u")){ char c = inb.substring(i+2,i+3).charAt(0); if(Character.isDigit(c) || c == '-'){ // get unicode number for(int fi=3;fi<9;fi++){ if(!Character.isDigit(inb.substring(i+fi,i+fi+1).charAt(0))){ try { if(c == '-'){ n_unicode = -Integer.valueOf(inb.substring(i+3,i+fi)).intValue(); } else { n_unicode = Integer.valueOf(inb.substring(i+2,i+fi)).intValue(); } break; } catch(java.lang.NumberFormatException e) { break; } } } } } // convert japanese if(!breadfont && i < inb.length()-8 && inb.substring(i,i+2).equals("\\\'")){ byte v1,v2; v1 = (byte)Character.digit((char)inb.substring(i+2,i+4).getBytes("iso-8859-1")[0],16); v2 = (byte)Character.digit((char)inb.substring(i+3,i+4).getBytes("iso-8859-1")[0],16); String code = ""; if(!bsymbol && !breadrule){ b2[0] = (byte)(v1 * 16 + v2); if(inb.substring(i+4,i+6).equals("\\\'")) { v1 = (byte)Character.digit((char)inb.substring(i+6,i+7).getBytes("iso-8859-1")[0],16); v2 = (byte)Character.digit((char)inb.substring(i+7,i+8).getBytes("iso-8859-1")[0],16); b2[1] = (byte)(v1 * 16 + v2); if(cset.equals("")) code = new String(b2,"SJIS"); else code = new String(b2,cset); skip += 7; } else { v1 = v2 = 0; if(isRtfChar(inb.substring(i+4,i+5).charAt(0))){ b2[1] = inb.substring(i+4,i+5).getBytes("iso-8859-1")[0]; if(cset.equals("")) code = new String(b2,"SJIS"); else code = new String(b2,cset); skip += 4; } else { b1[0] = b2[0]; if(cset.equals("")) code = new String(b1,"iso-8859-1"); else code = new String(b1,cset); skip += 3; } } } else { b1[0] = (byte)(v1 * 16 + v2); if(!breadrule){ code = new String(b1,cset); if(cset.equals("")) code = new String(b1,"iso-8859-1"); else code = new String(b1,cset); } else code = new String(b1,"iso-8859-1"); skip += 3; } String ascii = escapeString(code,n_unicode); if(ascii.indexOf("\\u65533") > 0){ System.out.print(inb.substring(i+0,i+skip+1)+" : "); System.out.print(code+": "+cset+" : "+ascii+" : "); for(int ci=0;ci<code.length();ci++){ int v = code.charAt(ci); System.out.print(code.charAt(ci)+"["+v+"]"+", "); } System.out.println(); } fos.write(ascii.getBytes("iso-8859-1")); i += skip; bbackslash = false; n_unicode = -1; } else { char ch = inb.charAt(i); if(ch == '\\') bbackslash = true; else if(!isRtfChar(ch)) bbackslash = false; if(breadfont || bbackslash || !bsymbol || !isRtfChar(ch)) { fos.write(ch); } else { byte[] sb = new byte[1]; sb[0] = inb.substring(i,i+1).getBytes()[0]; String ascii = escapeString(new String(sb,"MacSymbol"),-1); fos.write(ascii.getBytes("iso-8859-1")); } } if(breadfont){ if(inb.substring(i,i+1).equals(";")){ breadfont = false; } } if(breadrule){ if(inb.substring(i,i+1).equals("}")){ breadrule = false; } } } fos.close(); } catch(UnsupportedEncodingException ex) { ex.printStackTrace(); } catch(IOException ex) { ex.printStackTrace(); } catch(Exception ex) { ex.printStackTrace(); } return tmpfile; } /** RTF unicode 文字列かどうか **/ private static boolean isRtfChar(char c) { if(c == '\r' || c == '\n') return false; if(c == '\\' || c == '{' || c == '}' || c == ' ') return false; return true; } private static String escapeString(String str,int n_unicode) throws IOException { StringBuffer sb = new StringBuffer(); if (str == null) { return ""; } int sz; sz = str.length(); for(int i = 0; i < sz; i++) { char ch = str.charAt(i); int v = ch; // handle unicode if(ch > 0xfff) { if(n_unicode > 0) { if(v != n_unicode){ sb.append("{\\u"); sb.append(v); sb.append("}"); } } else { if(v != 0x10000 + n_unicode){ sb.append("{\\u"); sb.append(v); sb.append("}"); } } } else if(ch > 0xff) { sb.append("\\u"); sb.append(v); sb.append("? "); } else if(ch > 0x7f) { sb.append("\\u"); sb.append(v); sb.append("? "); } else if(ch < 32) { switch(ch) { case '\b': sb.append('\\'); sb.append('b'); break; case '\n': sb.append('\\'); sb.append('n'); break; case '\t': sb.append('\\'); sb.append('t'); break; case '\f': sb.append('\\'); sb.append('f'); break; case '\r': sb.append('\\'); sb.append('r'); break; default: if(ch > 0xf) sb.append("\\u"+v); else sb.append("\\u"+v); break; } } else { switch(ch) { case '\'': case '"': case '\\': case '{': case '}': sb.append('\\'); sb.append(ch); break; default: sb.append(ch); break; } } } return new String(sb); } /** 文字列から1行ずつ抽出 **/ private static ArrayList splitLine(String s) { String body = s; body = body.replaceAll("\\Q\r\n","\n"); body = body.replaceAll("\\Q\r" ,"\n"); String[] ss = body.split("\\Q\n"); ArrayList v = new ArrayList(); for(int i=0;i<ss.length;i++) v.add(ss[i]); return v; } /** RTFファイルから1行ずつ抽出 **/ public static ArrayList readRTF(File file) { StringBuffer sb = new StringBuffer(); File tmpfile = ConvertJapanese(file); try { InputStream is = new FileInputStream(tmpfile); InputStreamReader isr = new InputStreamReader(is);//UTF-8 RTFEditorKit rtf = new RTFEditorKit(); javax.swing.text.Document doc = rtf.createDefaultDocument(); rtf.read(isr,doc,0); if(doc.getLength() != 0){ sb.append(doc.getText(0,doc.getLength())); } else { JOptionPane.showMessageDialog(null,"対応しないRTFフォーマットです。"); } } catch(Exception ex) { System.err.println("RTF read error: "+ex); } return splitLine(sb.toString()); } public static void writeRTF(String filename,String str) { File file = new File(filename); try { OutputStream os = new FileOutputStream(file); StyleContext sc = new StyleContext(); DefaultStyledDocument doc = new DefaultStyledDocument(sc); Style n_style = sc.addStyle("normal",null); RTFEditorKit rtfwriter = new RTFEditorKit(); StyleConstants.setFontFamily(n_style,"serif"); doc.insertString(0,str,n_style); rtfwriter.write(os,doc,0,doc.getLength()); } catch(Exception ex) { System.err.println(ex); } } public static void main(final String[] args) throws Exception { System.setOut(new PrintStream(System.out, true, "UTF-8")); ArrayList r = readRTF(new File("multilingual.rtf")); for(int i=0;i<r.size();i++){ System.out.println(r.get(i)); } writeRTF("myoutput.rtf","Hello RTF Document!!\n日本語でこんにちは。\n韓国語で\uc548\ub155\ud558\uc2ed\ub2c8\uae4c\n"); } } [ メッセージ編集済み 編集者: gami 編集日時 2006-10-06 21:06 ] |
1