2012年12月22日

commonsのdigesterを使用してXMLロード

今更感は否めないが、Javaのapache commons-digesterを使用して、
XMLファイルの読み込みを作成してみた。(バージョンは1.8)

XMLを読み込むには読込ルールが必要で、
それをコーディングもしくは外部ファイル(XML)で定義することになる。

やはり、外部ファイルだろうということで、そちらを選択した。

書き方はいくつかのサイトで紹介されている。
例えば、、、
http://www.syboos.jp/java/doc/xml-to-java-object-by-digester.html
http://www.h7.dion.ne.jp/~s_wat/jakarta/digester.html

ということで、少し詰まったところを以下に残すことにする。

・特定のタグが来たら、タグのテキスト(Body)を引数にして指定のメソッドを呼ぶ





ここでは、"tag/item/value"という構成のタグが出たら、
"addItemValue"というメソッドを実行するようにしている。
詰まったのは、paramcountのところだ。
このattributeを付けないと、引数無しのメソッドが呼ばれてしまう。
paramcountだから引数の数かと思って1とすると、それも外れ。(確か、タグのattributeの1つめを引数にしようとする、、だったような)
正解の0を指定すると、タグのテキストを引数としてくれる。
なんだか直感的には分かりにくい。

・ルールファイルと対象のXMLファイルを読み込む

FileInputStream ruleIn= new FileInputStream(rulePath);
Digester digester = DigesterLoader.createDigester(new InputSource(ruleIn));

FileInputStream queryIn = new FileInputStream(queryPath);
Utsuwa info = (Utsuwa) digester.parse(queryIn);


いくつかのサイトで書かれていたDigesterオブジェクトを作る方法がdeprecatedになっていた。
"createDigester(new File("sampleRule.xml").toURL())"の"toURL()"が。
なんてことはないが、代わりに上のようにすれば動く。


なんといってもメリットは、XML読み込みがルールファイルのみで柔軟に変更できることだろう。
構造が多少変わっても、ルールを変えるだけで済む。

以上とします。
ラベル:java
posted by Thoughter at 17:47| Comment(0) | TrackBack(0) | Java | このブログの読者になる | 更新情報をチェックする

2012年12月19日

FileのlistFilesを敢えて試した結果

Javaで、あるディレクトリ直下にあるディレクトリ・ファイルの一覧を取得したい。

その時よく使われるのは、FileクラスのlistFilesだ。

listFilesには引数無しメソッドに加えて、オーバーロードが2つあって、
それぞれFileFilterとFilenameFilterを引数にとる。

もう既に様々なサイトで使用方法は示されているけれど、
敢えて全パターンを書いてみて、一番”格好良い”のはどれか見てみた。

条件としては以下だ。
・そのディレクトリには、ディレクトリとファイルが存在しているが、必要なのはファイルのみ。
・ファイルといってもjarファイルのみが欲しい。(拡張子が.jarで判断)
・メソッドの戻りはListで欲しい。nullになっちゃう配列は嫌!

そして、こんな感じのソースを書いた。(全力で)

public class ForTest {

private static final String PATH = "U:\\test";
private static final String TARGET_EXTENTION = "jar";

public static void main(String args[]){

for (int i =0 ; i<1000; i++){
filterPatternA();
filterPatternB();
filterPatternC();
}
}

private static void filterPatternA(){
File[] farr = new File(PATH).listFiles();
List flist = new ArrayList(farr.length);
for (File file : farr){
if (file.isFile() && file.getName().endsWith(TARGET_EXTENTION)){
flist.add(file);
}
}
}

private static void filterPatternB(){
File[] farr = new File(PATH).listFiles(new FileFilter() {
@Override
public boolean accept(File f) {
return f.isFile() && f.getName().endsWith(TARGET_EXTENTION);
}
});
List flist = Arrays.asList(farr);
}

private static void filterPatternC(){
File[] farr = new File(PATH).listFiles(new FilenameFilter() {

@Override
public boolean accept(File dir, String name) {
if (!new File(dir.getAbsolutePath() + "\\" + name).isFile()) return false;
return name.endsWith(TARGET_EXTENTION);
}

});
List flist = Arrays.asList(farr);
}

}



そして、約3400ファイルあるディレクトリ(U:\test)で実行。
ついでに実行時間も計測(まぁいろんなサイトで速度は変わらん!と言っているが)。
1000回ループさせた。

平均値をとると、A:115.29ミリ秒、B:117.168ミリ秒、C:120.384ミリ秒。
誤差もいいとこ。
やるだけ無駄。速度に優劣無しと判断する。


ところで、本題はどれが一番格好良いか。
Cはあまり好きじゃないなぁ。
FilenameFilterでファイルかどうかを判断するのはスマートじゃないね、きっと。

AかBか、ぱっと見で分かりやすいのはAではないだろうか。
一覧とって判断してるのね、と直感的に分かる。

だけど、やっぱり格好良いのは、Bに決定する(謎
If文無いし。(厳密には書き方なだけだが。。。)

いやいや、AのIf文のところをリファクタリングして、
分かりやすいメソッド名を付けるのが一番格好良いでしょ!という意見もありそう。。。

そういや、該当ファイル無しのときにnullで落ちるのは愛嬌で。。。
勢いで、null判断を入れるの忘れた。

そんじゃ、甲乙つけがたしで(笑
ラベル:java
posted by Thoughter at 22:37| Comment(0) | TrackBack(0) | Java | このブログの読者になる | 更新情報をチェックする

2012年12月17日

Javaとlog4Jとrsyslog

Javaからlog4JでLinuxのsyslogを介してログ出力をしたいときはどうするか。

色々なブログで紹介されている。例えば、以下だ。
http://www.nurs.or.jp/~sug/soft/log4j/log4j8.htm
http://d.hatena.ne.jp/kuromoyo/20120229/1330510365
http://vaindespair.blogspot.jp/2009/01/log4j-syslog-in-centos5.html

私は、log4j.propertiesをこのように設定して出力してみた。
単純に、/var/log/messagesにログを出力するだけのものだ。

log4j.category.cat=INFO, syslog

log4j.appender.syslog=org.apache.log4j.net.SyslogAppender
log4j.appender.syslog.Facility=local0
log4j.appender.syslog.SyslogHost=hostA
log4j.appender.syslog.Header=true
log4j.appender.syslog.layout=org.apache.log4j.PatternLayout
log4j.appender.syslog.layout.ConversionPattern=%C{1} - %m%n


結果の雰囲気はこうなる。
Dec 15 20:31:36 hostA LogSender - info message

ちなみに、hostAはLinuxのHost名で(というか今回の場合、上記設定のSyslogHostの値)、
LogSenderは実行したクラス名だ。
info messageは任意で指定した文字列。
HeaderをTrueにしておくと、勝手にsyslogっぽい日時とホスト名が付加される。



ところでタイトルはsyslogでなくrsyslogだ。
syslogに比べると、rsyslogの方が情報が少ない。

rsyslogはsyslogの設定をそのまま使用できる信頼できるsyslogだ。

rsyslogの場合にメッセージを受信するには、
/etc/rsyslog.confファイルの以下部分のコメントを外すだけでよい。
(あくまで、ローカルの話。リモートから出力するなら、以下の設定変更もある。)
http://www.atmarkit.co.jp/fjava/rensai4/devtool12/devtool12_3.html


# Provides UDP syslog reception
#$ModLoad imudp
#$UDPServerRun 514
 ↓コメントを外す
# Provides UDP syslog reception
$ModLoad imudp
$UDPServerRun 514

これでUDP514ポートで受け取ることが出来る。

最後に、service rsyslog restartなどでデーモンを再起動してあげてください。

若干気になっているは、レイアウトの%pオプションでもホスト名が出てくる件。
なぜかlocalhostとなっていた。
勿論、Linuxのホスト名は変えている。
気になるけれど、大したことではないのかもしれない。
ラベル:java Linux
posted by Thoughter at 21:14| Comment(0) | TrackBack(0) | Java | このブログの読者になる | 更新情報をチェックする

広告


この広告は60日以上更新がないブログに表示がされております。

以下のいずれかの方法で非表示にすることが可能です。

・記事の投稿、編集をおこなう
・マイブログの【設定】 > 【広告設定】 より、「60日間更新が無い場合」 の 「広告を表示しない」にチェックを入れて保存する。


×

この広告は90日以上新しい記事の投稿がないブログに表示されております。