ヒマをみつけてWeb開発
その場の思い付きを、ヒマをみつけてWebサイトにしてみるブログ

Propertiesクラスでnative2asciiを実装

Monday, 20 November 2006 00:00 by sabro

Javaでnative2asciiを実装の件ですが、Propertiesクラスを使って実装してみることにしました。

もともとnative2asciiは、Propertyファイルに日本語文字列を格納するためのツールであり、PropertiesクラスはそのPropertyファイルを読み込んだり書き込んだりするわけで、なにかしらの変換手段を持っているはずだからです。

JavaDocを見ると、どうやらgetProperty、setPropertyメソッドを使っているだけではUnicode変換は発生しないようです。storeメソッドでStreamに書き出したり、loadメソッドで読み出したりする際に変換が発生するとのこと。

実際にstoreメソッドで「あいうえお」と保存したとき、以下のように保存されていました。=以下の部分が変換後の文字列です。うまくこの部分を取得できれば変換が出来そうです。

##Sun Nov 19 22:55:25 JST 2006=\u3042\u3044\u3046\u3048\u304A

さらに今回はメモリ内で処理を完結させたいので、StreamにはByteArrayOutputStream、ByteArrayInputStreamを使います。以下ソースです。

Properties p=new Properties();
ByteArrayOutputStream bos=new ByteArrayOutputStream();
p.setProperty("", "変換文字列");p.store(bos, "");
int index=bos.toString().indexOf("=");
return bos.toString().substring(index+1).replaceAll("\\=", "=").replaceAll("\\:",":").replaceAll("\\#", "#").replaceAll("\\!","!").replaceAll("\\\\","\\");

変換する文字列をsetPropertyで格納し、storeメソッドでその内容をByteArrayOutputStreamに保存します。そして=以下の部分をsubstringで取得します。「#、!」はコメントに使われる文字なのでエスケープされています。最後の行でこれをエスケープされてない状態に戻しています。同様にkeyとvalueの区切りに使われる「=、:」、Unicode文字の先頭に使われる「\」もアンエスケープしています。

デコードのソースは以下です。

Properties p=new Properties();
ByteArrayInputStream bis=new ByteArrayInputStream("=".concat("変換文字列").getBytes());
p.load(bis);
return p.getProperty("");

文字列の前に=を連結してByteArrayInputStreamに保存した後、空文字をkeyとしてgetPropertyで取得するとデコードされます。

これで何とかnative2asciiは実装できそうです。ついでにURLエンコードとかも出来るようにしようかと考え中です。

Tags:  
Categories:   Java
Actions:   Permalink | Comments (43) | Comment RSSRSS comment feed

Javaでnative2asciiを実装

Saturday, 18 November 2006 00:09 by sabro

HTMLエンコードツールに、native2ascii機能も追加しようと思っていろいろ調べてみました。

とりあえず検索してみたんだけどライブラリは見つかんない。直接native2ascii.exeを呼び出すのはあんまりやりたくなかったので、native2asciiタスクを持っているAntの実装をパクッて参考にしてみることにしました。

検索してsun.tools.native2ascii.Mainというクラスを使っているところを発見。しかし、なぜかインスタンスを直接生成せずリフレクションを使ってクラスを取得しています。このクラスはtools.jarに含まれているそうなので、とりあえずプロジェクトでtools.jarを参照してみました。

でも、なぜかインテリセンスに上記クラスが現れません。無理矢理宣言してもコンパイルエラーになります。どうやらこういうことらしいです。sunパッケージ以下のクラスは将来的に動作が変更される可能性があるから使わないでくださいとのこと。それで、Antでもリフレクションで呼んでたのか。っていうかAntはこの注意事項を守ってないんですね。ある意味男らしいです。

まずはリフレクションのgetDeclaredMethodsメソッドでsun.tools.native2ascii.Mainが持っているメソッドの一覧を取得してみました。publicなメソッドが3個しかありません。

public static void sun.tools.native2ascii.Main.main(java.lang.String[])
private static java.nio.charset.Charset sun.tools.native2ascii.Main.lookupCharset(java.lang.String)
private void sun.tools.native2ascii.Main.error(java.lang.String)
public synchronized boolean sun.tools.native2ascii.Main.convert(java.lang.String[])
public static boolean sun.tools.native2ascii.Main.canConvert(char)
private java.lang.String sun.tools.native2ascii.Main.formatMsg(java.lang.String,java.lang.String)
private java.io.BufferedReader sun.tools.native2ascii.Main.getA2NInput(java.lang.String) throws java.lang.Exception
private java.io.Writer sun.tools.native2ascii.Main.getA2NOutput(java.lang.String) throws java.lang.Exception
private java.lang.String sun.tools.native2ascii.Main.getMsg(java.lang.String)
private java.io.BufferedReader sun.tools.native2ascii.Main.getN2AInput(java.lang.String) throws java.lang.Exception
private java.io.BufferedWriter sun.tools.native2ascii.Main.getN2AOutput(java.lang.String) throws java.lang.Exception
private static void sun.tools.native2ascii.Main.initializeConverter() throws java.io.UnsupportedEncodingException
private void sun.tools.native2ascii.Main.usage()

convert関数の引数に、入力ファイルパスと出力ファイルパスを渡すことで一応変換は出来ました。以下動作したコードです。

Class n2aMain = Class.forName("sun.tools.native2ascii.Main");
Method convert = n2aMain.getDeclaredMethod("convert",new Class[]{String[].class});
Object o = n2aMain.newInstance();
convert.invoke(o,new Object[]{new String[]{"C:\input.txt","C:\output.txt"}});

ファイル経由以外ではダメみたいでした。しかも、エンコードは出来てもデコードができません。(なんかデコードに使われてそうなprivateメソッドはもってるのに。)

メモリ内で処理完結できて、デコードにも対応する方法がないかもう少し探してみることにします。

Tags:  
Categories:   Java
Actions:   Permalink | Comments (45) | Comment RSSRSS comment feed