2010年03月29日
JavaでSIGINTをハンドル
LinuxでJavaアプリを開発しているときに、Ctrl-Cでの終了をハンドルする必要が出た。
次の二つの方法でハンドル出来るけど、Ant経由で起動したからかハンドル出来たり出来なかったりする。
ちなみにAnt1.7.1 , Java1.6.0_13 fork=trueの環境。
謎・・・。
java標準ではないが、Sunのパッケージを使う場合
import sun.misc.Signal;
import sun.misc.SignalHandler;
Signal.handle(new Signal("INT"), new SignalHandler() {
public void handle(Signal sig) {
log.info("SIGINTを受信したためプログラムを終了します。");
System.exit(0);
}
});
Runtime#addShutdownHookでも出来る。こっちの方が標準ライブラリ内で出来るので良いかも。
Runtime.getRuntime().addShutdownHook(new Thread(){
@Override
public void run() {
log.info("プログラムを終了します。");
}
});
Antから実行すると、シャットダウンフックの終了を待たずにVMが終了するようで、シャットダウンフックの処理が実行されたりされなかったりするようだ。
Javaコマンドで実行した際にはシャットダウンフックの内容が正しく処理された。
Antを使いつつ正しくシャットダウンフックを行う方法は未調査。
2010年01月19日
Javaでグローバルフック
現在、SWTを用いたアプリケーション開発をしていて、グローバルフックを使った入力が必要になった。
通常Javaからはグローバルフックは無理だけど、SWTの拡張でグローバルフックを使う事が出来るライブラリがあったので使ってみる。
次のような事が出来る。サンプルもあるので気軽に動作を確認する事が出来る。
# Window Decorations: making windows always-on-top, transparent, flashing on the taskbar, etc.
# Custom Shape Window: creating non-rectangular windows using custom Regions.
# Access to Windows Registry.
# Shell Folders: getting paths and icons of the user folders (Favorites, My Pictures, etc)
# Shell Links: managing the system link files.
# System Info: gathering CPU, memory, system variables information.
# Hooks: using system hooks and allowing to intercept some system events.
# System Menu Manager: managing the shell system menu, user can define custom menu item.
# Windows Session: managing system session. User can logoff, shutdown, reboot computer.
# Ole Control: providing some ole control wrappers, such as flash.
グローバルフックでマウスのイベントを取るやり方。
Mouse_LLHook.addHookInterceptor(new Mouse_LLHookInterceptor() {
public InterceptorFlag intercept(Mouse_LLHookData hookData) {
int wParam = hookData.getWParam();
switch (wParam) {
case Mouse_LLHookData.WM_LBUTTONDOWN:
// 左クリック
break;
case Mouse_LLHookData.WM_RBUTTONDOWN:
// 右クリック
break;
}
return InterceptorFlag.TRUE;
});
Mouse_LLHook.installHook();
使い終わったら Mouse_LLHook.unInstallHook(); して解放しないとダメ。
2009年11月26日
XP にマホトーンをとなえる for Java
XPを使っていると死ぬほどうざい「コンピュータの更新を完了させ、更新を有効にするには、コンピュータを再起動してください。」と言うダイアログ。
それを黙らせる「XP にマホトーンをとなえる」と言うアプリがおもしろかったので、それのJava版を作ってみたw
実行するときはSWTのライブラリをクラスパスに追加してね!!
import org.eclipse.swt.internal.win32.OS;
import org.eclipse.swt.internal.win32.TCHAR;
public class XPにマホトーンをとなえる {
public static void main( String[] args ){
XPにマホトーンをとなえる まほうつかい = new XPにマホトーンをとなえる();
まほうつかい.マホトーンをとなえる();
}
private void マホトーンをとなえる(){
TCHAR じゅもん = new TCHAR(OS.CP_INSTALLED, "自動更新",true);
int えっくすぴー = OS.FindWindow(null, じゅもん);
OS.ShowWindow(えっくすぴー, OS.SW_HIDE);
}
}
仕組みは単純で、自動更新のウインドウを非表示にしてるだけ。
邪魔なウインドウを画面外にドラッグするのが一番手っ取り早いがw
2009年06月18日
INDRIのJavaインターフェイスコンパイルエラー
仕事でINDRIと言う新しめの検索エンジンを使うことになった。
言語モデルと推論ネットワークを組み合わせて、良くなったぜ的なものらしい。
C++で書かれているが、JavaやPHPで使用できるラッパーがある。
で、そのJavaAPI部分のcompileに失敗していたので解決方法を。検索しても英語の情報すら出てこなかったので誰かの役に立つことを願ってメモしておく。
普通にlemur-4.9を落としてくる。
$ ./configure --prefix=$HOME --enable-java --with-javahome=$JAVA_HOME --with-swig=/usr/bin/swig
としてmakeするが、次のようなエラーが出る。次のエラーメッセージは4.6のものだけど、まぁこんな感じでJavaのコードがめちゃくちゃになってる。
/JAVA_HOME/javac -classpath java -d ../obj/java java/lemurproject/lemur/ArrayAccumulator.java
java/lemurproject/lemur/RetrievalMethod.java:12:
public abstract class class RetrievalMethod {
これはJavaのコードを自動生成したswigのバージョンが古いからのようだ。ちなみにCentOS4.4に最初から入っているswig1.3.21でおかしいコードが自動生成されているようだ。
最新のswig1.3.39を入れてmakeすると正しくinstallすることができた。
2008年09月11日
アスペクト指向プログラミングで自動ログイン処理
一時期オブジェクト指向プログラミングの次はアスペクト指向プログラミングだ!とか言われていたけど、Web開発してなければあまり使う機会がない。(置き換わるものではないのでこの説明は正しくない)
しかし、今回例のサイトに自動ログイン機能を付けることになり、アスペクト指向プログラミング(以後AOP)が必須となったので使ってみた。
通常のログイン機能は、あるフォームにID、パスワードを入力しSubmitするのでログイン機能が一カ所に集中しているので問題ない。
しかし自動ログイン機能は、ログアウト状態の時にどこかのページを見たら、そのページの処理の前に自動ログイン処理を行わなくてはならない。そして何事もなかったかのようにリクエストされたページを処理し表示する。
AOPが無ければすべてのActionのメソッドの開始時に"自動ログイン処理"を自分で追加しなくてはならない。
しかしAOPがあれば「この処理をすべてのActionのメソッド開始前に実行してね」と書くと、後は自動でやってくれる。
AOPを使うことで便利になるような横断的関心事はそれほど多くない。
例としては今回のような自動ログインとかトランザクション管理とか、AOPの説明で良く出てくるロギングぐらいか?
SeasarだとAOPもサクッとできたのでメモを残しておく。
まずorg.aopalliance.intercept.MethodInterceptorをimplementsしたクラスを作成する。
これが織り込まれる処理となるので、処理をinvoke()に書く。
今回はこんな感じだ。
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
HttpServletRequest request = getRequest();
HttpServletResponse response = getResponse();
execAutoLogin(request , response);
Object result = methodInvocation.proceed();
return result;
}
methodInvocation.proceed();で実際の要求された処理を実行している。
SAStrutsの場合、戻り値は表示するJSPなので、そのままreturnする。
HttpServletRequestなどはS2Containerから取得する。
S2Containerはpublicなフィールドにしておくと勝手にDIされる。
よって
HttpServletRequest request = (HttpServletRequest)container.getComponent(HttpServletRequest.class);
などして取得。
そしてapp.diconに
<component name="autoLoginInterceptor" class="foo.bar.AutoLoginInterceptor"/>
とかしてコンポーネント登録。
次に、実際にActionに処理を織り込む設定をする。
Actionをカスタマイズするためのcustomizer.diconを修正する。
コンポーネント名がactionCustomizerのところに
<initMethod name="addAspectCustomizer">
<arg>"autoLoginInterceptor"</arg>
</initMethod>
と追加する。
これで完了、楽ちんぽん!
自動ログイン処理は以下のように実装した。
通常ログイン時に、乱数を生成し、その乱数をさらにSHA-256でハッシュしキーを作成する。
そのキーを"チケット"としてCookieに保存。同じチケットをユーザ情報としてDBに保存。
ログアウト状態でページを表示しようとすると、CookieとDBのチケットを比較。同じであれば自動ログイン成功。
成功すると新しいチケットを発行しなおして次回の自動ログインに備える。
発行し直すことで同じチケットは1回限りしか使用できないようにする。
また、自動ログインした場合はセッションに自動ログインフラグが立ち、そのフラグが立っている場合にアカウント情報修正など重要な処理を実行する場合は再度認証を行うようにする。
ログアウトボタンを押下した場合はチケットを破棄し、自動ログインを無効にする。
とりあえずこんなもんでいいっしょ。
自動ログインは本来セキュリティ上好ましくないけど、特にクリティカルな情報を扱うわけでもないしこのサイトでは良いよね!
2008年06月23日
loader constraint violation
SAStrutsはすばらしい。スーパーアジャイルなStrutsと言うことで、RoRに対抗してサクサク感を最大化したとのふれこみは伊達じゃないな。
Strutsもまぁ悪くはないんだけど、テンポは確かに悪い。めんどくさいし。
めんどくさいと言う要素は結構くせ者で、趣味のプログラミングでは「あれ作ろうかな。でもめんどくさいしやめとこ。」と言うことになり、先に進めなくなる。これはまずい。SAStrutsはstruts-config.xmlと言う呪縛から解放されるので、気軽にプログラミングができる。
そんな快適なSAStrutsだけど、今さっき躓いた。
クラスローダー関連のエラーLinkageError : loader constraint violationが出てしまう。
SAStrutsはHotデプロイ機能のため、動的にクラス定義を変えることができるようになっているんだけど、Seasar管理外の部分と連携するとクラス定義に不整合が起こるようだ。
具体的にはSAStrutsのWebアプリから通常のServletへ、とあるインスタンスをsetすると発生する。
SAStrutsのSeasar用クラスローダと、TomcatのWebappClassLoaderとがぶつかっているようだ。
ふーむ。どうすれば良いんだろう。
通常ServletもSeasar用クラスローダを使うHotデプロイ対象にすれば良いのか?しかしどうやって?
Hotデプロイをやめれば問題は出ないだろうけど、それではSAStrutsの意味がない。
SAStrutsとServletの連携が変態過ぎると言うこともあるけど、Cometの実装の都合上Strutsだけでは実現不可能だ。
SAStrutsとCometServletとの間をSocketにしたりして結合度を下げる解決策もあるだろうけどめんどくさい上になんか邪道だ。
うーん。どうしよう。
2008年05月28日
スマートなプロパティ変更通知
あるオブジェクトのプロパティが変更された場合に、他のオブジェクトへ通知する必要がある場合は多い。
自分で実装しても良いが、JavaBeans用の既存の仕組みを使わせてもらう。
具体的にはイベント通知のサポートをしてくれるPropertyChangeSupportをフィールドに持ち、PropertyChangeListenerを外部から受け入れ、任意の箇所でPropertyChangeSupport.firePropertyChangeを呼び出して各リスナに通知する。
以下のページに簡単に解説してある。
プロパティの変更を通知する仕組みを作成する
プロパティのバインドとサポート・クラスの利用
簡単便利でお手軽により協調的な仕組みを作ることができる。ナイス。
2008年05月27日
Readability over Convention
最近、流行のS2Daoを試してみた。
S2DaoはCoC(Convention over Configuration:あるルールでコードを書けば設定ファイルなんて要らないZE☆)と言う思想で、設定ファイルを極力書かずにORマッピングができるので非常に便利だった。アクセステーブル名はクラス名、カラム名はプロパティ名、DAOの検索メソッドはselectから始まるメソッドなど。制限も少なく、さくさく書ける。あとはフレームワークが全部してくれる。iBATISとかHibernateと比べると圧倒的に楽だ。
が、Ruby on Railsで流行りだしたCoCブームも一段落すると欠点も見えてきたようだ。
CoCだと規約(Convention)を理解していないと、何をやっているか全くわからないという点だ。(全くというのは言い過ぎか)
CoCはおそらく開発者のリズムを崩さないと言う要素を最大化する思想なので、精通した技術者が少人数でガシガシコードを書くには最適だと思われる。
しかし現実のプロジェクトでは人の入れ替わりは激しいし、人によって技術の差も大きい。
よってそんなときCoCは足かせとなってしまう。
と言うことで、それは問題だ!と思う人向けにS2JDBCと言うのが出てる。
こちらは既存のフレームワークのリズムの悪さと、CoCの規約まみれの解決策として可読性を最大化するように設計されているようだ。
こちらはまだ全然使っていないので、何とも言えないが、コードを見る限りよさげだ。
たとえば検索クエリは以下のようになる。
Listresults = jdbcManager.from(Employee.class).join("department")
.where("id in (? , ?)", 11, 22)
.orderBy("name desc")
.getResultList();
S2DaoよりもSQLを細かいところまで自動生成してくれるようなので、S2JDBCの方がさくさく書けるかもしれない。
Web系Javaはこういう「こんなん便利じゃね?」「いやいやこういうやり方こそスマートだ!」みたいなのがどんどん出てくるので面白いな。
おそらく、全部のフレームワークの良いところばかり集めたバランスの良いフレームワークが一番なんだろうけど、今はまだ試行錯誤の段階でRuby on RailsやS2Daoのような提案手法に特化したものが出尽くすのを待つ時期なんだろう。
2008年04月21日
GEFがスタンドアローンではうごかないっぽ
Eclipse上で簡単にグラフィカルなエディタを作成することのできるGEFを使って、仕事で使うツールを作成しようとしたら以前よりEclipseランタイムとの結合が強くなっているのかどんどんEclipseのライブラリを要求され、そのうち「Eclipseが初期化されてないぜ!」とか怒られた。つまり自分で作ったアプリの上でGEFだけ使いたいと言うことができない。Eclipse上のプラグインとしてならもちろん動作するだろう。
ふーむ、Eclipse2.0時代のGEFならいけたんだけど・・・。
GEFのFAQを見てみると以下のように書いてあった。
Can I develop a standalone GEF application without use of the Eclipse platform?The official answer is No, this is not supported. The main reason involves the use of an
Eclipse-specific file titled plugin.properties which GEF uses for string externalizations.
However, since GEF is an open source project, modifications to the GEF codebase could
potentially allow a GEF editor external to Eclipse.
ふぐぐ・・・。無念。
古いバージョンのGEFでやってみるか。古いGEFでも多少Eclipseのライブラリを要求されたので同じバージョンのをそろえるのが大変そうだが。
2008年03月25日
Antのビルドファイルのプロパティを外部ファイルに書き出す
Antは強力なビルドツールなので、コンパイルに成功したらJarに固めてSSHでアップロードとかまで自動で行ってくれる。
が、SSHのパスワードももちろん必要で、ビルドファイルにパスワードを書くのは一人だけで使用するならかまわないがプロジェクトを共有するならまずい。
よってIDパスワードなどのプロパティを外部ファイルに書き出し、その外部ファイルだけ個人個人で設定するようにする。
以下のように、プロジェクトディレクトリ外にファイルを置き、参照する。
<property file="${user.home}/ant.common.properties"/>home以下のパスワードファイルはもちろん600に。
後はいつものようにプロパティを使う。たとえば以下のような感じ。
<scp file="${jarFile}" todir="${loginID}:${loginPassword}@127.0.0.1:/home/USER/dist/" trust="yes"></scp>
よってよりナイスになる。便利。
2008年01月04日
AjaxとCometを用いたチャットサイトを作った
この正月ひたすらプログラミングしてCometを使用したチャットサイトを作った。
http://anime-freaks.net/chat/
Cometとはプル型の通信しかできないHTTPの使い方をちょっとひねって、サーバ側からプッシュ型の通信をできるようにした技術。
従来のWebチャットでは定期的なリロード時間がn秒として、誰かが発言してからそれを受信するまで平均n/2秒の遅延が発生していた。
しかしこの技術を使うことで、誰かが発言すれば次の瞬間全クライアントがその発言を受信することが可能になる。
Cometを用いたリアルタイムWebチャットはLingrが有名だ。
Lingrはチャットルームに"入室"しないと発言ができず、またチャットルームは誰かが作成した誰かの部屋だ。
今回作成するのは2chのような誰もが自由に匿名で書き込みができ、なおかつチャットルームは誰かの所有物ではなくオープンなスペースになる。もちろん個人のプライベートなチャットルームも作成可能にする予定。
これにより"入室"しないと発言できないLingrより敷居は低くなり、より活発な(そして荒れ気味にもなる)チャットプラットホームを実現することができる。使用用途は主に実況系を想定している。
以下感想。
Cometを用いたチャットの中心プログラムはすぐにできたけど、Ajax部分や慣れないTomcatの設定あたりで結構時間がかかったな。相変わらずIEとFirefoxなどブラウザごとにJavascriptの挙動が違うので苦労した。後はいろいろ調べてApacheとtomcatを連携させたと思ったらApacheの方がCometに対応してなくて結局Comet部分は連携できなかったり・・・・。
あとHTTPの仕様的には同じサーバにTCPのコネクションを同時に2本まで接続することを推奨していて、これにより一つのチャットルームに入るだけで2本全部消費してしまうのが結構めんどかったな。
1本は新規メッセージ取得用、もう1本はメッセージ投稿用だ。
このときほかにもう1本コネクションを張っていると、3本目のメッセージ投稿のコネクションを張ることができず、ほかのコネクションが切れるまで待ってしまう。よってメッセージを投稿することができない。
この問題はとりあえずチャットルームごとにドメインを分けることで解決した。
Firefoxはこれで解決したが、なぜかIEはコネクションを解放しないのか使っていないはずのコネクションを持ち続けて新しい接続を繋いでくれない。ちょっとIEでの挙動は調査が必要だ。
TCP Monitorで見るとページを読み込み終わってもTCPセッションが接続したままになることがあるからそれが原因かも。
あと先人の苦労としてLingrでの記事。
梅田サロン中止のお詫び、およびアーキテクチャ変更についての技術詳細レポート
というのがある。やはりちゃんと考えないとスケーラビリティの確保が大変なようだ。
うちのサーバも今のアーキテクチャじゃ対応できないのでそのうち変更しないとなぁ。
まぁ基本の考え方はよくあるDBのレプリケーションのようにマスターと多数のスレーブという構成でいけそうだ。
あと今回は、できる限り応答速度を速めるためにそれぞれの処理を多数のスレッドでのバケツリレーのように処理するようにした。こうしておくと今後のチャットサーバのクラスタ化にも役に立つだろう。
このときマルチスレッドでアクセスするので、データに対する処理にデリケートにならないといけないのだけど、Javaの強力な並行処理用パッケージが非常に助かった。同期がいらずノンブロッキングでスレッドセーフなキューのConcurrentLinkedQueueなんて涙が出るほどすばらしい。同期のいらなくて読み書き可能のCopyOnWriteArrayListも非常にうれしい。簡単にアトミックなカウンタが使えるAtomicLongも地味に助かる。
やっぱマルチスレッドはJavaだなと改めて思った2008年の正月だった。
CometとAjaxでチャットを作れて自分的にはだいぶ満足したが、作成したものはもったいないので世に出した方がよいとの助言を受けて、勢いに任せてドメインまでとってしまった。
とりあえずアニメ系の実況サイトにする予定。なぜアニメ系かというと俺がオタだから。最近は忙しくてアニメ見ることも少なくなって、アニオタというよりコンピュータGeekと言った感じだけど。
ドメインもとったことだしもうちょっと安定性を高めてしっかりしたものにしてみよう。
後は自然言語処理を用いていろいろとおもしろいアイデアがあるのでそれも試してみたいな。
あ、年末に注文していたキーボードは連休明けの8日に届く予定です。今はオンタリオ国際空港で出発待ちらしい。
ちょうどキーボードを必要としていた時期を見事に避けて届きやがります。
今年の正月はTVも見ずにプログラミングしてたので正月感が全くない。
世間的には"あけましておめでとう"なんだよな。ということで今年もよろしくお願いします。
2007年11月27日
罠 in tomcat
ある日、いきなり作成中のWebプログラム(Struts使用)が以下のエラーメッセージともに起動しなくなった。
致命的: サーブレット XXXXX がload()例外を投げました
javax.servlet.UnavailableException: パス jndi:/localhost/XXXXX/WEB-INF/struts-config.xml に対するリソース読み込みエラー
ネットで調べても原因がよくわからず、struts-config.xmlのフォーマットエラーだの、メッセージリソースがないからだの、何回か再起動したらそのうち直っただの謎だった。
設定ファイルを眺めても特にエラーがあるわけではなく、原因は不明だ。読み込みエラーと書かれているがもちろんそのファイルはある。と言うか昨日までちゃんと動いていた。
とりあえずtomcatとStrutsを最新にしても同じエラー。
結構悩んだ末に仕方なくtomcatとstrutsのソースコードを落としてきてステップ実行することに。
するとDirContextURLConnectionのconnectメソッドで失敗しているようだ。
注意深く見てみるとなんとコンテキスト名の先頭に/が無いとStrutsの初期化に失敗する模様・・・。
あれ、そんな仕様あったっけ・・・、と言うか/が無いなら補完してくれよ!
俺の3時間返してくれ!
ここまで悩んだのはエラーの原因が"ファイルが見つからないこと"とはわからなかったことだ。
例外を見てもUnavailableExceptionだし、ファイルが見つからないときのIOExceptionはチェーンされていなかった。
UnavailableExceptionの例外をnewする部分を見ると、なんとファイルが見つからないときの例外を無視し、設定ファイルのパースエラー時のメッセージとともにUnavailableExceptionを作成していた。設定ファイルパース時に何かエラーがあったら全部同じエラーメッセージ同じ例外かよ・・・。
例外は飲み込まずにチェーンしろよ!!と思ったがなんとUnavailableExceptionにはチェーン用のコンストラクタがなかった!!なんでやねん!!
ちなみになぜ前日まで動いていてソースいじってないのに動かなくなってしまったのかというと、おそらくEclipseのTomcatによる自動server.xml書き換えを実行するためにいったんTomcatプロジェクトの指定を外した事による再設定時の/付け忘れが原因だろう。
ネットでの情報が少なかったので俺のようなうっかりさんが今後参考になれば嬉しいなと言うことでメモを残す。
2007年09月26日
Antでビルドナンバー自動生成
Antでビルドナンバーを簡単に自動生成できることを知ったのでそのメモ。
まずbuild.xmlに
<buildnumber/>
と書く。
するとカレントディレクトリに「build.number」と言うファイルが作成される。
中身は以下の通り。
#Build Number for ANT. Do not edit!
#Wed Sep 26 13:21:46 JST 2007
build.number=4
ビルドした時間とビルドナンバーが自動生成される。
そしてこのファイルをjarの中に入れるようにし、プログラム実行時にjarの中のビルドナンバーファイルを読み込んでビルド時間とビルドナンバーを表示するようにすればOK。
これで「その実行ファイルいつのヤツだよ!?」なんて悩まなくても良くなる。
便利。
2007年06月11日
Java Caching System Version 1.3 is available
JavaのキャッシュシステムJava Caching Systemがリリースされた。
Webアプリを作るときにMemcachedみたいなのJavaでないのかな?と思っていたのでこれは便利そう。
ちらっと見ただけで詳細はまだこれからだけど、分散キャッシュシステムなので複数台マシンでキャッシュクラスタみたいなのを作り、そのクラスタをひとつのMapのようにみなしてキーとそれに対応する値(Object)を保持できるようだ。
メモリだけでなく、閾値を越えたらディスクにキャッシュすることもできるのか。
キャッシュサーバはスケーラビリティのあるWebアプリケーションには必須だろうしナイスタイミングでリリースされたな。
Javaのキャッシュシステムは他に無いと思ってたけど以前からいろいろあるようだ。当たり前か。
Java用のシンプルなキャッシュ機構 - ehcache-constructs 0.6公開
ただFrequently Asked Questions "Is JCS faster than EHCache?"にyesとあるようにEHcacheより高速なようだ。
よし、必要ならコレを使うようにしよっと。
日本語で解説サイトできないかなぁ。
2007年06月08日
メモアプリ
自作の付箋紙的メモアプリ「どこでもノート」。自分で作ったは良いけど全然使っていない。
また、仕事マシンには付箋紙アプリ「付箋紙21」を入れてて以前使っていたけど今は使っていない。
現在メモは家のLinuxに接続し、Emacs上でChangeLogを取っている。
ChangeLogは日誌としてのメモには良いけど過去のメモの一覧性が悪い。
付箋紙アプリは日誌としては使いづらい。そして何より付箋紙アプリで不満なのはデスクトップ上が付箋紙で散らかりまくることだ。
Windows上では紙copiが便利だけど、Windows環境専用だし他にも様々な理由で使いたくはない。
Googleノートブックは便利だけどブラウザ上のみなのでちょと不便。もちろんGoogleノートブックはブラウザ上で動くというのがメリットだとは思うけど。
よって俺的理想最強メモアプリの要件 かっこ内は既存のアプリで要件を満たしているもの
・必要なときにサッと書ける (付箋紙アプリ,紙copi)
・画面がメモで汚れない (紙copi)
・データの一元化 (ChangeLog,Googleノートブック)
・日誌 (ChangeLog)
・高速検索 (Googleノートブック)
・タグ機能
・日付関連づけ機能 タグの日付版
・TODO機能 「TODO ○○」とメモればTODOリストに反映
・リマインダ機能 「2007/06/08 ミーティング」とメモれば通知してくれたりGoogleカレンダーに予定を登録
などなど、と言ったところ。メモ重視の日誌&カレンダー&TODOアプリという感じか。
どこでもノートは付箋紙アプリのWindows Linux共通版として作ったんだけど、そもそも付箋紙アプリというのが俺の要求を満たすシステムでは無かった。(作り始めた当時はそれで満足だと考えていた)
メモアプリと日誌アプリは同時には実現でき無さそうだけど、メモに対して日誌タグの付いているメモのみを作成日付でソートするビューを作ればできそうだ。
検索はGoogleノートブック以外はその都度全文検索をしているのでとても遅い。そのため作るアプリはLuceneなどを使ってインデックス化して高速検索を目指すと他のメモアプリとの差別化がはかれるかもしれない。
データの一元化はどこでもノートの場合FTPを使っていたけどFTPはレガシーでセキュリティ上よろしくないのであまり使いたくない。Google Data APIsを使ってGoogleノートブックとデータのやりとりができるからGoogleノートブックにデータを保存することでデータの一元化が実現できそうだ。データのやりとりを抽象化しておいてFTPにデータ保存などもできるようにしておくとさらによさげ。
どこでもノートのWiki的な他のメモへのリンクなどは使いやすかったのでそういう点は残しつつ、メモ + 日誌 + カレンダー(リマインダ) + TODO 的なアプリにしよう。
リマインダやTODOはメモの中に特定のフォーマット、たとえば「TODO ○○仕上げる」など書けばTODOとして認識されるなどすれば、メモとシームレスなTODOとして便利そうだ。
妄想を妄想として楽しみつつ、データのモデルぐらいから考え出すか。
今回はJava 並行処理プログラミングの本で培ったマルチスレッド処理をガンガン使ってみたいな。
ま、90%ほどの確立で途中で飽きると思うけど、「こういう設計にしたら実現できるな」などと考えるだけでもプログラマとしての経験値が上がりそうだし無駄じゃないだろう。
それと「こんなナイスなメモアプリあるぜ」とか「普通のアプリには無いけどこういうマニアックな機能があれば俺だけ便利」などあればココのコメント欄でも、また実際に会ったときでも教えてください。
2007年04月08日
LWJGLで日本語表示
テクニカルエンジニアの試験まであと1週間ですが、テストが近くなると部屋を片付けたくなる法則と同じように別のことをついつい考えてしまう。と言うことでJavaでのゲーム作成についていろいろ・・・・。
Javaで2Dゲームを作ろうとすると、Java2Dを使うかLWJGLのようなOpenGLを使うようなライブラリを使うことになる。LWJGLはゲーム用にジョイスティック使えたり音楽再生も楽そうなので良い感じなんだけど、英語環境で使うことしか想定していないので不便なこともある。他の人にとっては些細な問題かもしれないけど俺にとっては結構大きな問題だ。
それは何かというと日本語入力と日本語表示。のちのちチャットゲーやMMORPGを作りたいなぁと思って自分にとってはこれらは特に重要な要素になる。SwingでJava2D使ってゲームを作るのであればIMF(Input Method Framework)が使えるので、ゲームの画面内にチャットの入力部分を作成することができる。日本語表示にしても特に問題は無い。2Dをただ表示するだけなら、Java2Dでもかなり高速に描画できる。でも拡大縮小回転や透過を使うとなるとJava2Dではキビシイ。
Java2DはダメとなるとLWJGLになるわけだけど、こっちはこっちでいろいろ問題が・・・。
日本語表示に関しては、LWJGLはOpenGLなので描画するのは全部テクスチャになる。なので文字を出力するだけでもいちいちテクスチャ作成して・・となってややこしくなる。
と言うことで誰かが作ったLWJGL用文字列描画ライブラリ
Yet another glFont
このライブラリはフォントをビットマップに出力したものを用いて出力するタイプのもの。なので事前にフォントの全文字をビットマップファイルに出力する必要がある。その辺の出力は自動でやってくれるツールがある。記事に書いてあるけど日本語の場合はBitmap Font Generatorを使うとできる。
確かにこの方法だと綺麗に高速で文字が描画できて良いんだけど、日本語の場合は全文字のビットマップを作っていたらサイズがめちゃ大きくなる。さらに文字をビットマップに変換してそのファイルを再配布することになるのでフォントのライセンスも心配だ。
後は上の記事にも出てくるけど、Graphics2D使ってメモリに文字を描いて、そのデータからテクスチャを作成して画面に描画って感じか・・・。これも描画するたびに生成すると重すぎるので、文字ごとにキャッシュするようにしないとダメなんだよな。
日本語出力も問題多いけど、LWJGLでの日本語入力も大変だ。LWJGLはウインドウ自体がJavaのウインドウではないので、IMFを使うと言うことができない。一応AWT上でLWJGLを使うことができるので、IMFも使えそうだけど実際にやってみてないのでホントにできるかどうかは不明。さらにこの場合当然ウインドウのみでフルスクリーンにはできないだろう。(AWT使ってもフルスクリーンモードにはできるようだけど、その場合IMFが使えない予感)
ふーむ、LWJGLのおかげでJavaでゲーム作成はだいぶ楽になっただろうけど、海外製ライブラリと言うことで日本語入出力をしたいときはまだまだキビシイ。
C++&DirectXでやるとその辺一気に解決するんだけど、コードを書くのが壮絶にめんどい、特にサーバ。さらにオンラインゲーム用サーバがWindows用のみになってしまう。
クライアントはC++で、ゲームサーバはJavaでと言うのもありかなぁ・・・でもあまりやりたくない。
C++でちょこっとゲームは作ろうとしてみたけど、やっぱC++はめんどくさいのでモチベーションの低下が激しいw
↓テスト的に作ってみたオンラインRPGになる予定だったプログラム(C++とDXライブラリを使用) サーバはC++でSocket使用(DirectPlayはいろいろダメっ子らしいので)
やっぱJavaで作りてぇぇぇ!!
派手な画面効果と透過処理は捨ててJava2Dでゲーム作るか・・・。まずは画面内での日本語入力だな・・・。と言いつつ他に優先度の高い"やりたいこと"があるのでいつできるかは不明だけど。
2007年04月04日
Tomcat6でCometサポート
最近Tomcatの最新版が出た。
そして新機能としてCometのサポートがある。
記事は以下。
Tomcat 6の実力を早速試す - 移行するべき? その時期は?
CometはAjaxみたいに概念に名前を付けた感じの物で、簡単に言うと「HTTPを使用してプッシュ型のデータ配信を行う仕組み」の事。
今まではWebチャットのようなリアルタイム性が求められるアプリケーションでも、Ajaxを用いて10秒ごとなどにポーリングを行っていた。つまりこの場合平均5秒のタイムラグが出る仕様だったわけだ。ところがCometを使うと、サーバ側からのイベントとしてクライアントに通信できる。そのためプッシュ型のデータ配信が出来、チャットなどもリアルタイムに発言できるようになる。(Comet実装として有名なのはLingr、Googleチャットもそうなのかな?)
そんな今までの常識を覆すようなCometはどのように実装されているのかというと、かなり強引な手段を使っている。
1、ブラウザはとりあえず何もなくてもAjaxなどを用いてWebアプリケーションサーバにリクエストしに行く。
2、WebサーバはHTTPリクエストに応答せず、そのまま放置する!
3、Webサーバがデータをクライアントに送信したいタイミングで、放置していたHTTPリクエストにデータを含めて応答する。
4、ブラウザはイベントを受け取ったので、すぐさま1に戻り再びリクエストを投げる。
という感じ。今まではHTTPのリクエストがあれば、すぐに応答するという常識があったわけだけど、それを放置し任意のタイミングで応答するって言うのでプッシュ型を実現してる。う~ん、発想の転換。
しかし従来のサーバは、1コネクションに対し1スレッドを割り当てるため、コネクションが多くなると負荷が大きくなる問題があった。そんなにスレッドが多くなるのは想定してないのか、Linuxでも数千スレッドになるともういっぱいいっぱいとかどっかには書いてあったな。そのため1スレッドで複数のコネクションの面倒を見るようなサーバではないと対応できないらしい。
Tomcatは5までは対応できなかったけど、6から対応と言うことでCometを使いやすくなるのは良いことだ。一部のAjaxフレームワークでもComet対応されつつある。
そのうち時間が空いたら俺もCometつかって簡単なチャットでも作ってみようかな。
2007年03月13日
Google Guice
Googleが作ったDIコンテナGoogle Guiceの1.0がリリースされた。
Google Guiceのサイトはこちら。
これでGoogleジュースと読むらしい。
DIは直訳で依存性の注入で、簡単に言うとあるオブジェクトの属性や機能を外部から注入する感じ。
それにより依存関係が弱くなって実装を変更しなくちゃならない場合でも設定ファイルを書き換えるだけで実装を変更できる。と言うのがメリットだと言われているけど、それをメリットだと実感して「DIってスバラシィーーッ」って思ったことがないのでよくわかんない。
Webアプリ作成の業務でDIコンテナ使うことがあればそう思うのかもしれないけど。
と言うことでガイドはこちら。Springとはどうちがうねんと言うのはこちら。日本語でおkと言う場合はこちら(あるまに@monstar)。
Google社内でAdWordsのために開発されたとあるけど、AdWordsはJavaで動いてるんだなぁ。検索はC++だったような気がする。GMailやGoogle CalendarはGWT使ってるからこっちもJavaなんかな。
あるまに@monstarさんところで
>特にDIのパフォーマンスで困っている訳でも、XML定義が大きすぎて困っている訳でもない私がGuiceにちょっと興味を持っているのは、ソース見たらジェネリクスがすごい事になっていたからです。
>正直、最初見た時ソースの文法が一部理解できなくて「ジェネリクスをフル活用するとこんなソースになるのか!」と衝撃を受けました。
と言うことなので見てみた。
確かにジェネリクス使いまくりだ~。と思ったけど気になったのはインデントがスペース2個なのと拡張for文使ってるところが「おっ」と思った。
Google社内のコードはタブが2文字でのインデントが伝統という記事がどっかに書いてあった。創業以前からの社長のポリシーとかなんか書いてあったっけな。なのでコードを見るだけで社内のコードか外部のコードかが一目でわかるという。
拡張for文は以下のように書けるfor文の省略版。ListのitemListからitemを取り出しつつループする。
for( Item item : itemList){
item.use();
}
単に内部でIteratorを使ってるだけなので、Iterator経由の呼び出しにオーバーヘッドがあって、ArrayListの場合、単純にループの処理だけで3割ほど遅くなるとどっかに書いてあったので敬遠してた。
でも最近は「やっぱこれ便利じゃね?」と言うことで使いだしつつもある。
3割遅いって言ってもループ自体の処理の負荷なんて小さすぎるしループの中での処理の方が圧倒的に重いだろうしそう重要ではないよな。
でもJavaの拡張for文の不便なのは処理の負荷なんかじゃなく、perlのように添え字が自動生成できないところだ。
拡張for文で書いても、そのうち結局添え字が必要になってループカウンタ足したりする場面があるんだよな。
それにEclipseだと近くにあるリストや配列からfor文を自動生成してくれるし、拡張for文のメリットは見た目がすっきりする以外あんまり無い。
どうでも良いけどプログラマがfor文すらも自分で書かなくなってしまうとは恐ろしいことだ。
Eclipse便利すぎるぜ!
2007年03月01日
Struts + Spring + iBATIS
先日のiBATISはなかなか良い感じだ。
使ってみたところSQLは自分で書いて、検索結果のオブジェクト化などを自動でやってくれるのでコードを書く側としてはSQL書くだけでよいのでとても楽。SQLも書きたくない人はHibernateへ。
現在のiBATISにはDAO(Data Access Object)の機能が無いので、Spring Frameworkを使うことになる。
Spring FrameworkはDI(Dependency Injection:依存性の注入)のフレームワークで、今回はSpringのDBアクセス関連とトランザクション関連の機能を使う。
作りたいWebアプリがあるので、簡単にさくっと作りたいなと思ったんだけど、結局Struts + Spring + iBATISと言う王道な組み合わせになってしまったな。iBATISがHibernateなら、より王道だが。
Struts(Webアプリケーションフレームワーク)はさわったことあるけどSpringとiBATISは新しく学習するので割と大変だ。
とりあえずJava・J2EE・オープンソース Spring入門 ~より良いWebアプリケーションの設計と実装を読む。SpringとStruts、SpringとiBATISの連携方法ものっていて今回のプログラムには最適だ。
この本のSpringのバージョンは1系だけど、最新の2.0.2でiBATISとの連携をやってみたところ問題は無かった。
Strutsも深く理解しているとは言えないのでプログラミングJakarta Strutsを読んでみる。
また、DBは結局MySQLを使うことにしたのでMySQL 徹底入門 第2版を読んで勉強してみる。
ちょっとさわった感じではなんとシーケンスが無いことにカルチャーショックを覚えた。シーケンスの代わりにAUTO_INCREMENTと言うのがあって、出来ることはシーケンスと似てるけど使い方が違ったりで微妙に不便だ。データをINSERTするまで実際にふられるIDがわからないって言うのがなんかイヤだな。
2007年02月19日
O/Rマッピングフレームワーク
作りかけのプログラムがあるのに新しいアイデアにワクワクするのは悪いクセなんだけど、最近また「作りたいな~」と言うアイデアが出てきた。
そしてDBを使う必要があって、Javaでは結構前からJDBC使ってSQL書いてゴリゴリデータアクセスって言うのは今っぽくなくなってきている。O/Rマッピングフレームワークを使ってDBアクセスって言うのが今風だ。
以前はHibernateを使おうと思っていたんだけど、hibernateを利用してはいけない5つのシチュエーションを読むと「ここに情報を探しにきているようなひとは、悪いこと言いませんのでhibernateの採用を中止しなさい。」とある。
公式ページのドキュメントを読まず日本語で情報探すような軟弱者は手を出さない方が良いと言うことだろう。このページにはHibernateをよく理解せず利用した結果いろいろ困ることがある、と言う実例が書かれている。「よくわからないものを無理して使うからよ」と言うのは有名なセリフで、そこから学んだ結果、よくわからないし学習コストが高そうなHibernateはスルーすることにした。
となると残りはTorque、iBATIS、DbUtilsぐらいか。
DbUtilsは以前ちょっと使ったことがあるけど、JDBCを生で使うよりは良いかなと言うぐらいだったし、新しいものを試したいのもあるからパスで。
Torqueは実績があるらしいしなかなか良さげなんだけど、SQL書かなくて良いって言うのがなんか落とし穴になりそうだ。一応SQLも書けるようだけど。
と言うことでiBATISを使うことにしよう。iBATIS とはを読む限り、シンプルで学習コストも低そうだ。SQLを書かないとダメで、そうするとDBごとの互換性が無い訳だけど、マッピングファイルにSQLが分離されているので移行作業も楽だろう。そもそも趣味プログラミングなので違うDBに移行するという機会がほとんど無いのでOKだ。
公式ページを見るとドキュメントが豊富でチュートリアルもあるので安心だ。安心じゃないのは俺の英語力だけど。
しかし中国語や韓国語のドキュメントは置いてあるのに日本語のが置いてないとは。やっぱ日本だとHibernateがシェア高いのかな。Hibernateは和書もあるしなぁ。iBATISはインアクションシリーズが出てるけど和訳はされてないようだ。
とりあえずiBATISいろいろいじって遊んでみよう。
2007年01月24日
exewrap
Javaのexeラッパーにexewrapを使ってみた。
うん、すばらしいねコレは。
libディレクトリにjar入れておくだけで勝手にクラスパス通してくれるし、jreディレクトリにJava実行環境を入れておけばJavaがインストールされていなくてもOKだし。
起動に失敗するなどしても、エラーログをファイルに書き出してくれるし。
Javaで動いているのにもかかわらずプロセス名がラップexeファイル名になるし。
ただ、クラスパスをlibディレクトリ以外に設定できなさげなのが不便だなぁ。
メールで改善要望出したら改良してくれるかな?
antでexe作成自動化
<exec executable="Resource/exewrap/exewrap.exe" >
<arg value="-g"/>
<arg value="-a"/>
<arg value="-Djava.library.path=lib/win"/>
<arg value="-o"/>
<arg value="${dist}/DokodemoNote.exe"/>
<arg value="-i"/>
<arg value="Resource/dokodemonote.ico"/>
<arg value="${jarFile}"/>
</exec>
配布するときはJava実行環境を含めると便利そうだけどファイルサイズが結構大きくなる。
ちなみにJava 1.6.0の実行環境は無圧縮で80MBほど、圧縮すると30MBほどだった。
プログラム本体の5MBとあわせると35MBほど。
メモプログラムと考えるとサイズが大きいけどまぁ我慢できる範囲だ。
2007年01月12日
初トラバ
友人以外で始めてトラックバックをもらった。わ~い(*´Д`)
どんな人だろと思って相手の日記を読んでみると「ん?この記事読んだことあるな」と。以前いろいろ検索してるときにヒットしたページで、いろいろ興味深いことが書いてあったので仕事サボって読んでたページだ。世間は狭い。
このブログは友人数人のブログに書き込みなどしてリンクされているだけで、それ以外にはリンクされていないので検索エンジンでしかたどり着くことができない。(たぶん)
うちのサイトにはアクセスカウンタをつけていないので、どれぐらいのアクセスがあるかは知らないが(興味も無いが)アクセスログを見る限りちょっとは見てる人がいるようだ。
このブログは自分のメモ用と、そのメモを公開して同じ問題に出会った人の解決になれば良いかなと思って公開しているんだけどある程度は役に立っているようだ。
このブログでは「こんなん作ってますよ~」と言うのを書くこともあるけど、それをアウトプットとして出すことは無かった。
これからは「こんなん作ってます~」「でも公開してメンテするのがメンドイので自分だけで使います~」というのはやめてちゃんと出していかねば。
とりあえず今の時点で一番完成度の高いソフトはどこでもノートかな。
FTPサーバなどを使って複数のマシン上でメモを共有できると言うソフト。保存や同期が自動で行われるのでユーザーはそれらを意識する必要が無い。
エディタ部分は完成していて、後は通信部分の作りこみだけ。
一応動作するけどFTPサーバ通信時の排他処理が無いのでその辺作らねば。
あと、Windows環境だとexeから実行したいので、exeファイル作成ラッパーを使おう。
JSmoothやlaunch4jがあるけど、今回はexewrapを使おうかな。
前者二つはGUIが完備されていてオプションも豊富なんだけど、より便利と思える機能がexewrapに多いのでそちらを選んでみる。作者日本人ってこともあるけど。
exewrapにはantタスクが無いけど、コマンドライン一発だし大丈夫か。
これは使ったこと無いからいろいろいじってみよう。
実行可能Jarファイルを作る必要があるので、Jarファイルの仕様も確認する。
次に完成度が高いのはファイラかな・・・。
設計のうんこっぷりがすごくて作り直したい気分だけど。
2006年12月08日
ファイラ!
FFでは、ドラクエのメラ→メラミ→メラゾーマのように、ファイア、ファイラ、ファイガという風に強くなる。
でも今遊んでいるFF11では、ガ系はなぜか範囲魔法になってしまっている。ファイラの立場が無い。
と言うことで作りかけのファイラをちょっと修正。
今日はファイルコピー&ペースト、ファイルのエクスプローラへのドラッグでコピー、エクスプローラからのドロップでコピーを実装or機能強化。
しかし1年半も前のコードは、たとえ自分の書いたコードでも「なにこのクソコード!!読んでられねー!」という具合だ。1から作りたくなる衝動に駆られるッ・・・!!!
ファイル右クリック時に、選択されたファイルやディレクトリごとに違うメニューを出したいので、そのあたりの機能を考え中。頻繁にコードをいじる事が予想されるので柔軟に作れるようにしておかねば。プラグイン形式も考えられるけど、さすがにややこしくなりすぎるだろうから今回は見送り。
ファイルを選択するだけで、ファイルの中身を表示するファイルプレビュー機能もついてるけど、ココもファイルごとに実装が異なるので、柔軟に変更できるようにしておかねば。今はめちゃハードコーディングだしなぁ。
でもこのファイルプレビュー機能はわりと便利だ。
特にLinux環境だと、設定ファイルなどたいていテキストファイルなので、いちいちlessコマンドを叩かなくていいので便利。もっと機能強化して便利にせねば。
さらに勉強中の計算機プログラムの構造と解釈の宿題もやる。
まだ全体の1割にも達して無いのに難しくなってきた!
でもまだ時間をかけたら解ける問題が多い。
解けたときは「おお!正解!俺マジ天才!」とハッピーになれる。解けないと凹む。
今日はフィボナッチ数を対数的ステップ数で計算するアルゴリズムの問題がさくっと解けたのがとてもハッピーだった。
この本の問題は難しいけど、わりと楽しいかも。問題量も多いしこれで5000円は十分元は取れそうだ。途中で挫折しなければの話だけど。
でも1問解くだけでもパワーをめちゃ消費するので、勉強会とかやって半強制的かつ持続的に取り組まないと、絶対積読になるなコレは。
しかし最後までやりきると、何か悟りが開けそうな気がする・・・!
2006年09月23日
ブログ検索
検索エンジンがだんだん形になってきた。
まだいくつか問題があるけど、まぁなんとかなるでしょう。
4日データを集めて140万エントリー。結構なデータ量がすぐ集まっていいな。

今はブログのHTML全部取得してるから、検索文字列が純粋にエントリーだけじゃなく、タイトルや過去のエントリータイトルとかにも引っかかるんだよねぇ。
かといってRSSの中にはエントリーの前半特定文字数しか書いてないブログがあるし。Gooブログとか。
でもやっぱ検索して出てきたエントリーに、その検索単語の内容が書かれてる必要があるよな。ぬー。Gooブログはエントリーの前半しか検索対象にならないけど、それはしかたないってコトにするかぁ。
あと、今日フットサルの練習を昼すぎからしてたんだけど、朝ごはん兼昼ごはんにお好み焼きおなかいっぱい食べたら胃が重くて全然動けなかった... orz
運動するときはおなかへってるほうが動きやすいな。
で、コートの横に小学校のグラウンドがあって、運動会やってた。
なんか懐かしい感じ。いいなぁ。
2006年09月21日
プログラミングコンテスト
TopCoderと言うプログラミングの早さと正確さを競うプログラミングコンテストがある。
Google Code JamもTopCoderのシステム使って行われてるんかな。
内容は、3種類のそれぞれ難易度が簡単、普通、難しいの問題がある。ポイントは問題によってばらばら。んでそれぞれの問題を解くコードをいかに早く正確に書くかで、それぞれのポイントを上限としたポイントを得ることができる。
ためしに300ポイントの一番簡単な問題をやってみた。
問題を要約すると、0と1が並んでいる文字列を暗号化した文字列が与えられるので、それを復号するプログラムを書けと言うモノ。復号できないようなデータの場合はNONEを出力する。
暗号化アルゴリズムは、元の文字列Q[x]があった場合、暗号化文字列P[x]はP[x]=Q[x-1]+Q[x]+Q[x+1]となる。
011100011を暗号化したら123210122になる。
仕事サボりながら空いてる時間に解いたのでわりと時間かかったけど面白かった。
ほかの人のポイントともに書いたコードも見れるので勉強にもなる。
最大の問題点は俺が英語読めないということだ・・・。
これぐらいの簡単な問題なら問題文を適当に眺めて、入力と出力例みたらわかるけど・・・。
結構プログラミングの基礎能力をアップできそうなコンテストなので興味のある方は参加してみては。
とりあえず今日やった問題文書いておくので、チャレンジしてみるのもいいかも。
問題文の原文は以下(入力例は2個目以降省略してます)
Problem Statement
Let's say you have a binary string such as the following:
011100011
One way to encrypt this string is to add to each digit the sum of its adjacent digits. For example, the above string would become:
123210122
In particular, if P is the original string, and Q is the encrypted string, then Q[i] = P[i-1] + P[i] + P[i+1] for all digit positions i. Characters off the left and right edges of the string are treated as zeroes.
An encrypted string given to you in this format can be decoded as follows (using 123210122 as an example):
1, Assume P[0] = 0.
2, Because Q[0] = P[0] + P[1] = 0 + P[1] = 1, we know that P[1] = 1.
3, Because Q[1] = P[0] + P[1] + P[2] = 0 + 1 + P[2] = 2, we know that P[2] = 1.
4, Because Q[2] = P[1] + P[2] + P[3] = 1 + 1 + P[3] = 3, we know that P[3] = 1.
5, Repeating these steps gives us P[4] = 0, P[5] = 0, P[6] = 0, P[7] = 1, and P[8] = 1.
6, We check our work by noting that Q[8] = P[7] + P[8] = 1 + 1 = 2. Since this equation works out, we are finished, and we have recovered one possible original string.
Now we repeat the process, assuming the opposite about P[0]:
1, Assume P[0] = 1.
2, Because Q[0] = P[0] + P[1] = 1 + P[1] = 0, we know that P[1] = 0.
3, Because Q[1] = P[0] + P[1] + P[2] = 1 + 0 + P[2] = 2, we know that P[2] = 1.
4, Now note that Q[2] = P[1] + P[2] + P[3] = 0 + 1 + P[3] = 3, which leads us to the conclusion that P[3] = 2. However, this violates the fact that each character in the original string must be '0' or '1'. Therefore, there exists no such original string P where the first digit is '1'.
Note that this algorithm produces at most two decodings for any given encrypted string. There can never be more than one possible way to decode a string once the first binary digit is set.
Given a String message, containing the encrypted string, return a String[] with exactly two elements. The first element should contain the decrypted string assuming the first character is '0'; the second element should assume the first character is '1'. If one of the tests fails, return the string "NONE" in its place. For the above example, you should return {"011100011", "NONE"}.
Constraints
message will contain between 1 and 50 characters, inclusive.
Each character in message will be either '0', '1', '2', or '3'.
Examples
"123210122"
Returns: { "011100011", "NONE" }
The example from above.
以下例省略
2006年08月04日
コサイン尺度
文章の類似度を測るベクトル空間モデルで使う、二つのベクトルのコサインを出力するプログラムを書いてみた。
作ってから見つけたけど↓の本に詳細が詳しく載ってた。こっちの本には丁寧に解説されてあるので、作る前にこっちの本を読んでおけばよかったorz
内積ってどうやるんだっけとか、ノルムって何?どう計算するんだとか検索しまくったよ・・・。
public double getベクトルのなす角の余弦( double[] vector1 , double[] vector2 ){
if( vector1.length != vector2.length ){
throw new IllegalArgumentException("ベクトルの次元が一致しない");
}
double denominator = norm( vector1 ) * norm( vector2 );
double numerator = innerproduct( vector1 , vector2 ) ;
return numerator / denominator;
}
/** ノルム */
public double norm( double[] vector ){
double sum = 0;
for( int i = 0 ; i < vector.length ; i++ ){
sum += vector[i]*vector[i];
}
return Math.sqrt( sum );
}
/** 内積 */
public double innerproduct( double[] vector1 , double[] vector2 ){
double sum = 0;
for( int i = 0 ; i < vector1.length ; i++ ){
sum += vector1[i] * vector2[i];
}
return sum;
}問題はコレであっているかどうかだw
同じベクトルだと1になるし、ちょっと変えるとちょっと減る。一応あってそうだが・・・。
やってみたら単純な計算だけど内積って何だっけレベルのしょっぱい頭の俺にはハードだった・・・。
まず
の数式(俺にとっては暗号)の解読からつまずいたからなぁ。
人生、学校の勉強がいつ必要になるかわからないモノね・・・。
2006年08月01日
検索システムでけたー!
と言っても仕事サボりつつ、超シンプル版Webインターフェイスを10分ぐらいでw
ブラウザで表示し、検索単語を入力して実行ボタンを押すと検索結果が表示される。
検索対象はブログデータ17Gぐらい。インデックスファイルが700Mほど。
Web表示は生Servletを使った。Strutsとかフレームワーク使ってもよかったけど、どうせ今はシンプルな処理しかしないし。
公開するとかいろいろ考えるとセキュリティやらちゃんと設定しないとダメなので
などを読んでTomcatを勉強してみる。うひ~、本代がかさむ。
2006年07月21日
組み込みRDB
ブログのクローラーで、ブログリストの永続化をXMLファイルに保存という形を取っていたけど、いろいろ問題があるのでDBを使ってみる。でもわざわざDBを別に用意すると面倒なので、組込型のDBを使う。
組込型DBとはプログラムが開始したらそのプログラム専用のDBが立ち上がって、プログラム終了とともにシャットダウンする感じの便利な専用DB。
DBはおなじみApacheプロジェクトで開発されているDerbyを使う。
DerbyはJava6にJavaDBとして標準で付いてくることになっているので、いまから慣れておいて損はなさそうだ。しかし開発環境にフル機能のRDBが標準で付いてくるなんて結構すごいな。
以下は2chから引用のDerbyのマニュアル等々。日本語なのでわかりやすくてイイ感じ。CloudscapeとはApacheに寄贈される前のDerbyの名前。
IBM Cloudscape 概説およびインストール V10.1
http://publibfp.boulder.ibm.com/epubs/pdf/d8863601.pdf
IBM Cloudscape 開発者ガイド V10.1
http://publibfp.boulder.ibm.com/epubs/pdf/d8863611.pdf
IBM Cloudscape リファレンス・マニュアル V10.1
http://publibfp.boulder.ibm.com/epubs/pdf/d8863621.pdf
IBM Cloudscape チューニング・ガイド V10.1
http://publibfp.boulder.ibm.com/epubs/pdf/d8863631.pdf
IBM Cloudscape ツールおよびユーティリティー・ガイド V10.1
http://publibfp.boulder.ibm.com/epubs/pdf/d8863641.pdf
IBM Cloudscape サーバーおよび管理ガイド V10.1
http://publibfp.boulder.ibm.com/epubs/pdf/d8863651.pdf
同じJavaオープンソース組込型DBのHSQLDBをちょっと使ったことあるけどHSQLDBの方がサイズが小さくて高速。でも機能はDerbyの方が多いらしい。
2006年07月19日
ブログをクロール
ライブドアブログとGooブログの新着記事一覧からブログリストを取得するようにして、記事を集めるプログラムを走らせてみた。
数時間で5000件ほどのブログが集まり、データは3Gほどになった。
う~ん・・・、5000件で3Gか・・・、一瞬でHDがパンクしそうだなぁ。圧縮して保存もできるけどCPUパワーを消費するのは避けたいし・・・。形態素解析もデータ取得時に同時に行って保存しているんだけど、そのデータが結構大きい。分かち書きの情報だけ持っておくか・・・いやそもそもUTF-8からEUC-JPにするだけでもデータ量が2/3になるからな。ふ~む。
全文検索にはJavaのオープンソース検索エンジンのLuceneを使ってみる。自作するよりはるかに高機能でいろいろ考えられてるライブラリなのでいい感じ。先ほどの3Gのデータにインデックス張るのが15分ほど。検索は一瞬。
あとはWebの検索用フロントエンドを作成すれば一応ブログ検索エンジンはできるわけだけど、なんかただ組み立てただけって感じでツマンナイな。とりあえずWebの部分作った後考えるか。いろいろアイデアはあるけど壮大すぎてどこから手をつけたらいいかわかんない。
まぁでも作ってるといろいろ必要な技術が多くて楽しくはある。次はServletの勉強だ~。
2006年07月04日
分散システム
検索エンジンを作るとなると、1台のマシンですべてができるはずもなく、複数のマシンを使って動かすことになる。
また、複数CPUを有効に使うためにマルチスレッドを効果的に使う必要もある。
と言うことでその辺の記事など。
分散システムを作るにはJavaのRMIを使ってみようかと考え中。
RMI 入門
RMI
並列処理関連は
Java並列プログラミングTips
ここの参考文献のリンク先もなかなかよさげな記事が。
ついでに使用する形態素解析器Sen関連
SenはMeCabのJava版。一応MeCabにJavaバインディングがあるけどPureJavaのほうが何かと便利なのでSenを使うことにする。
速度はSenが数倍遅かったので、我慢できなくなったらMeCabを導入って事にしておこう。
sen プロジェクト ホーム
Sen Project
2006年06月21日
Javaでリモートデバッグ
プログラミングするときにデバッガでのデバッグは必須だ。
ログを出力して動作を確認するなどもできるが、やはりデバッガでステップ実行や条件一致のブレークポイントなどの方がデバッグしやすい。
しかし、サーバ上で動かしているプロセスに対するデバッグはログでのデバッグが中心になってしまい、面倒だ。
が、Javaだと別のマシン上で動いているプロセスに対してもデバッガでのデバッグが簡単にできて、とてもナイス。
この辺を参考にする
エクリプス リモートデバッグ
Eclipse Platformを使用したデバッグ
実行はとても簡単で、デバッグ対象のプログラム起動時にVM引数として
-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8000
などを指定して、いつも通りに実行。
その後、デバッグするマシンでEclipseの「debug」から「Remote Java Application」を新規作成し、接続先を指定する。
ポートはaddressで指定した値を設定。
接続すると後はいつも通りのデバッガなのでステップ実行や変数の値の読み書きなどやりたい放題だ。
HotSwapも使えるので実行途中にソースを書き換えるなんて事もできる。
2006年05月17日
Javaで暗号化と復号
サーバ保存型のノートの設定画面で、FTPサーバに接続するときのパスワードを入力する。
設定項目なので、もちろんプロパティファイルに書き込んで保存する必要がある。
しかし生テキストではあまりにも不用心と言うことで暗号化して保存する。
幸いにもJavaはデフォルトで様々な暗号化アルゴリズムが使えるようだ。
Java Tips:手軽に暗号化・復号化するには?とかを参照
暗号化はとっても簡単
SecretKeySpec sksSpec = new SecretKeySpec( KEY.getBytes(), "Blowfish");
Cipher cipher = Cipher.getInstance("Blowfish");
cipher.init(Cipher.ENCRYPT_MODE, sksSpec);
byte[] encrypted = cipher.doFinal(text.getBytes());
復号もとっても簡単
SecretKeySpec sksSpec = new SecretKeySpec( KEY.getBytes(), "Blowfish");
Cipher cipher = Cipher.getInstance("Blowfish");
cipher.init(Cipher.DECRYPT_MODE, sksSpec);
byte[] decrypted = cipher.doFinal(encryptedBytes);
暗号化アルゴリズムはBlowfishを使ってみた。
暗号は、暗号対象のバイト配列を入力して、暗号化済みバイト配列を出力するので、どんなモノでも暗号化できそうだ。
暗号化鍵はプログラム内に定数として保持、これは金庫に鍵をかけてその金庫の上に鍵を置きっぱなしにしているようなものだけど、パスワードの難読化という意味で目的は達しているのでまぁ良いだろう。
気になる暗号化、復号にかかる時間を計ってみた。
対象は青空文庫で公開されている「吾輩は猫である」のテキスト、サイズは731KB。
暗号化アルゴリズムはBlowfish、暗号化鍵は「abcdefgh」として時間を計ってみた。
結果、P4 2Gマシンで暗号化にかかる時間は1.2秒。復号にかかる時間は0.4秒。
他のアルゴリズムを試してないけど、思ったより速いのね。
2006年05月07日
どこでもノート
以前から作成中の、サーバ保存型ノートのネットワーク通信部分が完成した。やほーい!
![]()
以前からネットワーク部分はだいぶ完成していたけど、設計があまりにもダメダメすぎたので「1から作り直したい症候群」にかかってしまい、GW中はどうせ暇なので1から作り直してしまった。
ネットワークとの通信インターフェイスはFactory Methodパターンで、実装とインターフェイスを完全に切り離して設計。実際に通信に使う実装クラスをシステムプロパティに書いてあるクラスを使うことで、ソースをいじることなくどんなメディアを使っても同期が取れるようにした!
まぁそこまでする必要はホントはなくて、テストドリブン開発をしようと思うとFTPサーバがない環境でもテストを実行できる必要があってこういう設計になったわけだけど。
テストの時はローカルのファイルシステムを使って同期を取るようにした。これにより通勤の電車の中でもJUnitでの自動化された単体テストが出来るわけだ。
デフォルトではFTPサーバを使って複数のマシンでノートを共有するわけだけど、読み書きできればどんなメディアでも使えるので、その気になればFTPを使わずメールサーバを使って同期を取ったり、その辺の無料で借りれる掲示板を使っても同期は取れそうだ。
後は簡易FTPファイル共有機能とかその辺作って、細かい部分を実装したら完成だな。
ああ、複数のマシンで同時に同じノートを更新した場合のマージ機能もまだだな。
EclipseでCVSへコミットしようとすると、その二つのバージョンのソースでドコが違うかがグラフィカルに表示されて手動でマージできたりする。こういう機能でノートのマージも出来たら完璧だけどやっぱめんどくさいかw
![]()
2006年03月09日
WoodstoxでNoSuchElementException
XMLを読むAPIのSTaXの実装Woodstox(2.0.5)を使用中、変な現象が出たのでメモ。
XMLEventReaderを使用して while( reader.hasNext() ) して最後までXMLを読むわけだが、このときXMLEvent.END_DOCUMENTイベントをEventFilterでフィルタすると hasNext が期待した通りに動かない。
hasNextで、次があるよと言われているのに nextEvent すると次はもう無いと怒られる。
フィルタを使っているのでEventReaderはFilteredEventReaderを使うようになる。
ソースを読んでみると、FilteredEventReader#hasNextはXMLEventReaderのhasNextをそのまま呼んでいて、以下のようになっていた。
return (mState != STATE_EOD);
そしてFilteredEventReaderのnextEventは
while (true) {
XMLEvent evt = mReader.nextEvent();
if (evt == null || mFilter.accept(evt)) {
return evt;
}
/* ??? 11-May-2004, TSa: Should we take some precautions for
* END_DOCUMENT event? Or is above null check enough.
*/
}
となっていた。
つまりWstxEventReader#hasNextはフィルタとか関係無しにドキュメントの最後であるかどうかを返しているのに、FilteredEventReader#nextEventはフィルタされていないところまで一気にnextしてしまうのでEND_DOCUMENTがフィルタされていると必ずそのnextでNoSuchElementExceptionが投げられてしまうようだ。
う~ん、WoodstoxではEND_DOCUMENTをフィルタしたらダメなのかな?
仕様かもしれないけどドキュメントを読む時間もないしとりあえずXMLEvent.END_DOCUMENTをフィルタしないようにして回避。
コメントでEND_DOCUMENTにも気をつけるべき?と書かれているので、END_DOCUMENTをどうにかしないとダメだけどめんどいからイイやって事なのかもしれない。日付2004年だしこれはもう仕様って事なんだろうか。
開発者への連絡はメーリングリストしかないようだし、英語書くのもめんどくさいから・・と言うか英語書けないし放置でイイか。
しかしフィルタ用クラスのhasNextでフィルタしてない普通のhasNextをそのまま呼んでたらおかしくなるのは目に見えてるような気が・・・。
2006年02月09日
WoodstoxでStAX
以前StAXでのXML読み書きをちょっとやってみたが、ついに実戦で使うときが来た。
実戦と言っても趣味プログラミングの方でですが。
以前はBEAのプレビュー版なのかな?のライブラリでやってみたが今回はオープンソースでApacheライセンスなライブラリWoodstoxを使ってみる。
WoodstoxはライセンスをApacheライセンスとLGPLのどっちも採用していて、しかもライブラリのサイズも400kb以下というイイ感じなライブラリだ。
webから落としてきてstax-api-1.0.jarとwstx-asl-2.0.5.jarをクラスパスに入れて以前ココに書いたコードをそのまま記述すれば動く。快適。
使う目的は例のメモアプリ。
FTPサーバにメモをアップロードして共有するってことで。仕様的には 1メモ 1XMLファイル。
すべてのメモを1XMLファイルにしても良かったけど更新の衝突の場合めんどくさくなりそうなので分けてみた。
サーバ上にあるメモが更新されているかどうかは、一定間隔ごとにサーバ上のファイルリスト取得して確認って事にする。更新衝突の検出は、更新時に以前更新してからサーバ側にあるXMLファイルのタイムスタンプ取得して比較で検出。
ファイルの転送にはJakarta commons NETのFTP機能を使う。Commons VFSを使えばFTP,SFTP,WebDAVそれぞれに対応できるけどCommons VFSはまだ開発途中のバージョンだし安定してないと困るからとりあえずFTPだけで。
ネット関連機能は細かい仕様を決めてからやった方が良さそうだからWikiの方で考えとくか。
ネット機能が実装できたら一応最初のバージョン完成って感じかな。
ただ、今の実装方法だとメモが多くなったり、メモのサイズが大きい場合パフォーマンスに問題があるからその辺は直さねば。
2006年02月07日
RSSリーダ
ブログやニュースを読むのにRSSリーダは便利だ。
んで統合開発環境EclipseにもRSSリーダのプラグインRSS Viewがある。
が、微妙で使いづらい。
XMLデータ取得してそれ表示して、新着あったら通知って感じが欲しいけどまぁこれぐらいならすぐに作れそうだ。
JavaのRSSライブラリ
RSSLibJ
ATOMライブラリ(?)
BlogClient
2種類のフォーマットが勢力争いしてるのがめんどくさいが一応Javaで利用可能なライブラリは存在する。
でも読むだけだから自前でパースした方が早いかもしれない。
既存のプラグインRSS Viewの機能プラス版みたいなのはすぐに作れそうだけど凝った機能を付けようとすると大変になりそうだな・・・。gooのRSSリーダーをちょっと使ってみたけどこれぐらい高機能ならイイ感じだ。
でも時間無いしなぁ。AoE3も買っちゃったし。
こうやって欲しい機能とその実装方法を妄想してるのが一番ワクワクする時期だ。でもたいてい作り出してある程度まで形ができたら(ただしリリースできるほどの品質ではない)一気に冷めちゃうんだよな~。
んでネットを徘徊してたらRSSOwlを見つけた。
Java製RRSリーダ。日本語対応もしっかりしててイイ感じ。
一瞬Eclipse RCPかな?と思ったけど違うようだ。
EclipseのUI機能の一部分だけ抜き出して使ってるのかな?
RSSリーダを使ってみると結構便利で良い感じ。
今まではFirefoxのライブブックマークを使ってたけど専用のRSSリーダの方が高機能でこっち使った方がよさげだ。
他にもいろんなソフトをためしてみよっと。
2006年01月12日
Eclipse RCP
EclipseのRCPをちょっといじってみた。
RCPと言っても中身はEclipseのプラグインと同じなので
あたりを参考にした。
「Eclipse 3+Visual EditorによるJavaプログラミング」はRCPを作成する章があるので購入。画面写真付きで「ココにこのコードを追加してこのボタンを押す」とか丁寧にサンプルプログラムを作る手順が書いてあるが、"なぜココにこのコードを追加するのか"が書かれていないため本のとおりに最後までサンプルプログラムを入力して作ったとしても得られるモノはVisualEditorの操作方法だけだ。特にRCP作成部分は解説がほとんど無くてこりゃダメポって感じ。
まぁVEがメインの本だから仕方ないが・・・。
「Eclipseプラグイン開発」は実際に実用的なJUnitプラグインを作っていくのが主な内容。ちゃんと解説があり、しかもその解説の内容をどうやって調べてその方法が導き出せたかまで書いてあるので応用力も付きそうだ。
でも一つのプラグインを作っていく内容なのでそれに当てはまらない機能などは載ってない。これ一冊だけでもダメそうだ。
そもそもプラグイン開発はEclipseと言う既存のものに機能を追加するが、RCPは0から機能を作るので同じ技術を使うけどアプローチが違うって感じでやっぱRCP専用の本が欲しいところ。洋書読めやと言われればゴメンムリポって言うしかないが。
まぁとりあえずいろいろいじってちょっと作ってみたがEclipseのワークベンチの機能がそのまま使えてやっぱナイス。
拡張ポイントを自前で用意しておけば他人が勝手にそこを拡張するプラグインを書けたりするので、拡張性も抜群のプログラムができる。
ただ最初からそれを見越した設計をしないとダメだが。
趣味のプログラミングだとその辺適当にやってしまうからなぁ。
EclipseのリッチクライアントプラットフォームってことでIBMは流行らせたい感じだけどどうなんだろ。
一般企業向けのシステムのクライアントを作るとしたらメンテナンス性を向上させるぐらいしかプラグインにするメリット無いし。
使い道とすれば大まかな機能を作っておいて、それをそれぞれの企業に合うようにプラグインを追加したり修正して納品って感じだろうか。
WebサービスではJavaが優位に立ったがリッチクライアントでもJavaが頑張って欲しいところだ。
そのためにSunには「リッチクライアント?以前からSwing+JavaWebStartって言ってるじゃん。何を今更」と言うのではなくリッチクライアント向けに何か新しい技術を出してもらいたいな。
2005年12月26日
サーバ型付箋紙その2
以前書いた付箋紙(?)アプリをちょっとずつ実装中。
一応ノート部分はできた。
ノート部分の機能はLinuxでのメモアプリTomboyのまるパクリ。
Tomboyはノートの1行目がタイトルとして使用され、別のノートの本文中にそのタイトルがあれば自動的にリンクが張られるといった感じ。
やってることは単純なのですぐに実装できた。
現在データはローカルにXML形式で保存しているがサーバ型にするのはサーバの用意が大変だしFTPを利用するようにするか。
ノート1枚ごとに1ファイルに対応させるようにして変更があったらバックグラウンドで勝手にアップロードみたいな感じで。
2005年12月14日
Eclipse RCPその2
Eclipse RCPでソフトを作る。
参考
RCP Tutorial: Part 1
RCP Tutorial: Part 2
そしてこのページには手動で、作成したプログラムの単独起動を設定しているがめんどくさいしそのあたりも自動でやってくれる機能があるので使う。
EclipseのPackage ExplorerでRCPのプロジェクトを右クリックし、「New - Other」でProduct Configurationを選択。
テストで使用したRunを選ぶとそのRunの設定そのままで実行できる環境をExportできる。
Archiveを選択すると解凍するだけでインスコ完了なZipファイルを作成してくれる。スバラシイ。
で、やってみるとわかるがWindows環境だとWindows版しか出力してくれない。
画面にも書いてあるがマルチプルな環境で動くのを出力したい場合はRCP delta packなるモノをインスコする必要があるようだ。
で、それはドコにあるのかというとEclipseのDownloadsのRCP SDKのトコにある。そしてdelta packインスコ。
次に、require fragmentsを設定しろとあるように、Configuretion画面へ移動し、Add Required Plug-insボタンを押し必要なPluginを追加する。
いつも通りExportするが、その時Export wizardの一番下に Export for multiple platform と言うのがあるのでチェックを入れる。
するとその次にどの環境で動かすか選択できるので希望の環境を選択する。
そしてExportすると
application.linux.gtk.x86.zip
application.macosx.carbon.ppc.zip
application.win32.win32.x86.zip
のようにそれぞれの環境のアーカイブが出力される。MacはわからないがLinux版は動作確認できた。
スバラシイッス!
Javaアプリは配布が面倒だがこれなら実行ファイルが自動で作成されるので便利だ。
実行ファイル名も設定可能。
アイコンも設定可能でWindowsなら16x16から48x48のサイズのアイコンまでそれぞれ個別に設定可能だ。
いたせりつくせり。
起動に多少時間がかかるなどあるがドッキング可能なフレームワーク&簡単な配布を考えるとやっぱりEclipse RCPはイイカンジなようだ。
次作るアプリからRCP使っていこっと。
2005年12月12日
Eclipse RCP
Eclipse3.0からリッチクライアント向けの開発が楽にできるように対応した。
と言ってもよくわからなかったので放置しておいたのだが最近よくリッチクライアントと聞くようになったのでEclipseRCPについてちょっと調べてみた。
Eclipse Rich Client PlatformはEclipseのようなプラグイン形式のプログラムを簡単に作れて、自動更新とか機能も簡単に使えることができるよ。と言うモノで、Eclipse自身もEclipse RCPで作られている。
Eclipseはプラグインの集合体なのでEclipseからプログラミング関係のプラグインを全部取って業務アプリのプラグインを追加したらEclipseがその業務アプリになる、という感じか。
Eclipseの仕組みそのままだと聞くとなんだか重たく巨大そうに感じるがEclipseのコアとSWT/JFaceだけで6Mほどなので、大量のプラグインを除けばEclipseは軽くて小さい。もちろんSWT/JFaceの素のアプリに比べると重いだろうが。
参考は
ObserveEclipse - RCPアプリケーションを作成する
リッチクライアントというとWebアプリのように配布が簡単でなければならない。
Eclipse RCP自体にはそのような機能はないが既存の技術を組み合わせればOK。
と言うことでEclipse RCPで作成したアプリケーションをJava Web Startで配信するフレームワーク。
WebRCP
実際に動かしてはいないので暇なときに実験してみよう。
と思ってWebRCPのチュートリアルを動かしてみたがJavaWebStart起動→WebRCP起動→サンプルプログラム起動と3回もプログラムの起動があるので起動が遅い・・・。起動に10秒ほどかかるのは厳しいな・・・。
現在開発中のファイラにRCPを使えればEclipseのような高機能なドッキングが使えて便利そうだがすべてをプラグインの形式で作成するのはめんどくさそうだ。
でも技術的には面白そうだし・・・。むむむ。
2005年12月07日
Java普及度
JavaのニュースリンクサイトJava Newsで次のような記事を見つけた。
加速するJava利用、オープンソースのSourceForgeサイトでC++を追い抜く
本家SourceForgeでJavaのプロジェクト数がC++を抜きトップになったそうだ。
ちなみに日本のSourceForgeはどうかというと言語別一覧にもあるように日本でもJavaがトップのようだ。
ところでJavaのプロジェクトの数が本家は16954もあるのに日本のは297とは・・・。桁というかそれ以前の問題で少なすぎるな・・・。まぁ日本人の多くも本家を使っているだけかもしれないが・・。
ちなみに俺も日本のSourceForgeで一つプロジェクトを登録しておいた。例のファイラーだ。まだあげてないけどある程度の完成度になったらコミットする予定。
SourceForgeはLinuxのアプリを落とすときなんかはよく目にする。
当然LinuxのアプリはCやC++だ。確かにJava製もあることにはあるけど数は少ない。
まぁ開発ツールでJavaプロジェクトが多いんだろうけどもっとクライアント向けにJavaアプリが頑張って欲しいところだ。
そのためにも例のファイラーの開発を進めなければ。
2005年11月18日
Eclipse 3.2 M3
3.2のM3が出た。
注目のSWT新機能はOpenGL機能が追加された。
OpenGL部分はLWJGLが使われるようだ。
ソースをちょっと読んでみたところ枠はSWTでグラフィック部分はLWJGLそのもののようだ。スバラシイ。
Window表示はSWTでそこからフルスクリーン表示とかできるのかな。できたら神。試してみたいけどとりあえず放置。
2005年10月27日
続StAX
先日ちょっと使ってみてStAX微妙かもと思ったがStAXでXML書き込みをやってみたらめちゃ簡単だった。
今までXML書き込みはDOMばっかり使っていたけどStAXの簡単さを覚えてしまうとDOMはめんどくさくてやってられないって感じだ。
以下のコードを実行するだけで下のXMLが出力される
XMLOutputFactory fac = XMLOutputFactory.newInstance();
XMLStreamWriter writer =fac.createXMLStreamWriter( new FileOutputStream("testout.xml") ,"UTF-8");
writer.writeStartDocument();
writer.writeStartElement("root");
writer.writeStartElement("item");
writer.writeAttribute("itemNumber","1234ごろくなな\\円");
writer.writeCharacters("テキスト");
writer.writeEndElement();
writer.writeStartElement("item");
writer.writeComment("これはコメントです");
writer.writeEndElement();
writer.writeEndDocument();
writer.close();
出力されるXML、実際はインデント、改行されない。
<?xml version="1.0" encoding="utf-8" ?>
<root>
<item itemNumber="1234ごろくなな\円">テキスト</item>
<item>
<!-- これはコメントです -->
</item>
</root>
1から新しいXMLファイルを書き出すにはとてもとても便利だ。
割と直感的に使えるので簡単だしナイス。
でもDOMのようにXML読み込んでちょっと修正してそれを保存って言うやり方はできない。
相変わらずStAXの日本語情報は皆無なのでIBM developerWorksでStAXを検索するといろいろドキュメントが出てくる。
StAX゚+.゚(人・∀・)゚+.゚ イイワァ♪
2005年10月25日
StAXでXML
現在、JavaでXMLをいじろうとすると二つの方法がある。
SAX(Simple API for XML)とDOM(Document Object Model)だ。
DOMは欲しい情報だけ取得できて便利だが、一度にすべてのデータを読み込みデータ構造をメモリに持つのでメモリの消費が激しい。
SAXは文字通りシンプルでメモリ消費も少ないが複雑なXMLを処理しようと思うとプログラマの負担が大きい。
それぞれの弱点を考慮し、この二つの良いトコ取りをした新しいAPIがStAX(Streaming API for XML)だ。
と言うところまではよく聞く話だが実際よくわからなかったので使ってみた。
とりあえずこの辺からライブラリを入手。
しかしStAX!StAX!って聞く割には情報がない・・・。
StAX XMLで日本語ページを検索しても1000件ぐらいしかヒットしないし・・・。ヘッドフォンのSTAXもガンガンヒットする。
とりあえずJavaWorldにあったサンプルで試してみる。
StAXにはCursor APIとEvent Iterator APIの二つがあるらしい。
そして今回はCursor APIを使ってXMLを読み込む。
// 初期化
XMLInputFactory f = XMLInputFactory.newInstance();
XMLStreamReader r = f.createXMLStreamReader( filename , new FileInputStream(filename));
while( r.hasNext() ){
r.next();
// r.getText()やらr.getEventType()やらする
}
おお、すげー簡単。SAXよりもシンプルなんではなかろうか。
しかしあまりにシンプルすぎてこれではプログラマの負担がSAXと変わらない気が・・・・。
まぁ確かになじみの深いIteratorのように使えるからイベント駆動のSAXよりかは使いやすそうだが。
Cursor APIと言う名前の通り最初から1エレメントずつ読み込んでいく感じでSAXに対する別の解なのかもしれない。書き込みもできるのでSAX使うならこっちかなぁって感じ。
Event Iterator APIも気になったので調べてみた。StAX Event Iterator APIでググると日本語の情報8件・・・。頑張れStAX。仕方なく英語の情報で探す。この辺とか。
XMLEventReader r = f.createXMLEventReader( filename , new FileInputStream(filename));
するだけでEventReaderが取得できる。
後はCursor APIと同じようにr.nextEvent()すればXMLEventが取得できる。
・・・、ってそれだけ?
Cursor APIを通して取得できる情報がXMLEventと言う形でまとまってボコッと取得できるぐらいの差しかないのかな・・・。
SAXとDOMには弱点があるからStAXを作ったぜ!みたいな前評判(?)だったのでちょっと興味があったが俺が期待していたようなモノではなかったようだ。
DOMの代わりにはならないがSAXの代わりとしては便利そうな予感。むしろSAX要らないかも。
巨大なXMLファイルを書き込む必要があるならStAXしかないと言う場合もありそうだ。
ちなみに300バイト程度のXMLファイルを読み込むのに200~250ミリ秒かかっていた。
XMLInputFactoryのインスタンスの取得に100ミリ秒。
XMLStreamReaderのインスタンスの取得に100ミリ秒。
このあたりはDOMやSAXと同じぐらいだろうか。
読み込みが開始すれば速いが、小さなXMLファイルを大量に読み込む必要がある場合はちょっと遅いかもしれない。
2005年10月22日
2005年10月20日
Jakarta-Commons VFS
現在JavaでExplorerクローン作成している。
すでに最初の開発バージョンで俺が最初に必要としていた「Linux上でのファイル一覧の閲覧とダブルクリックでMP3の再生」は実現できていたがもっと高機能なファイラにしてSourceforgeあたりでオープンソースプロジェクトとして公開しようかと思う。
で、JakartaプロジェクトのCommonsでいろんなファイルシステムを抽象化するライブラリ VFSを使ってみると面白そうなので使ってみる。
コレを使うとローカルファイルシステムもHTTPもFTPも圧縮ファイルもWebDAVも同じように使える。
つまりExplorerのCドライブやDドライブなどの隣にFTPのホストが同じように表示され同じようにファイルのコピペなどが行うことができるわけだ。
圧縮ファイルは中身のファイルの読み込みだけらしい。
また、Java標準のファイルを扱うオブジェクトはファイルの移動や、ディレクトリの削除が非常に面倒だった。
が、このライブラリではそのあたりが解消されていて別のディスクに移動や、FTP上に移動なども簡単に行える。
ただディレクトリを"移動"すると移動先に同じ名前のディレクトリがあった場合、上書きせずに削除してから移動になるようだ。
このあたりは不便そう。自分で実装する必要がありそうだ。
FTPの接続がうまくいかなかったのでパッシブモードで接続する方法を以下に。
設定方法がわからなかったのでソース読んで解決。ドキュメント少なめでソース読むの必須かも。
単にドキュメント探し切れてないだけかもしれないけど。
以下のコードを実行するだけでローカルのtestディレクトリとその中のファイルをアップロードすることができる。簡単!
FileSystemManager fsManager = VFS.getManager();
String copyDir = "test";
FileObject file1 = fsManager.resolveFile("file:///c:/" + copyDir);
FileSystemOptions opt = new FileSystemOptions();
FtpFileSystemConfigBuilder cb = FtpFileSystemConfigBuilder.getInstance();
// パッシブモードON
cb.setPassiveMode( opt , true );
FileObject file2 = fsManager.resolveFile("ftp://USER:PASSWORD@HOST/DIR/"+ copyDir , opt );
file2.copyFrom( file1 , new FileSelector(){
public boolean includeFile(FileSelectInfo arg0) throws Exception {
return true;
}
public boolean traverseDescendents(FileSelectInfo arg0) throws Exception {
return true;
}
});
2005年08月26日
Groovyを実行可能シェルスクリプトに
Groovyで書いたスクリプトをPerlのようにスクリプトファイルだけで実行したい。
普通は
#groovy hello.groovy
とするが
#./hello.groovy
としたい。
ファイルには以下のように書く
#!/usr/bin/env groovy
println "hello world!"
もちろんgroovyにパスが通っていることと、JAVA_HOMEの環境変数が設定されていることが必要。
またスクリプトファイル名がクラス名になるのでファイル名にハイフンが含まれていると正しく実行できない。
2005年08月04日
猿にシェイクスピアの劇を書かせる
今は夏休み中。
暑いのは嫌いなので引きこもり中。
しかしすげー暇だ。
そんなときRFC2795 The Infinite Monkey Protocol Suite (IMPS)を見つけた。
猿にタイプライタを打たせてシェイクスピアの作品を作るというプロトコルだ。
あ、なんかおもしろそう。と言うことで俺も作ってみた。
アルファベット小文字+スペースをランダムに選び、入力した文章に一致するまでループさせる。
3文字ぐらいまでなら一瞬だけど5文字6文字ぐらいから時間がかかるようになる。
this is a penのスペースを含む13文字を作り出すにはどれくらい時間がかかるだろうか。
スペースを含む27文字の13乗だから
4052555150000000000通りの組み合わせかな。
とりあえずプログラムを動かして寝た。朝起きてもまだ正解は出ていなかった。
現在94億回目。猿に「コレはペンです」を書かせるだけでも大変そうだ。
405京ある組み合わせのまだ94億だからなぁ。なんか終わる予感がしない。
今回のプログラムでJava5からの新機能であるprintfみたいなヤツを試してみた。
StringBuilder sb = new StringBuilder();
Formatter formatter = new Formatter(sb, Locale.JAPAN);
formatter.format( "%02d:%02d:%02d", hour , min , sec );
で処理し、formatter.toString()で結果取り出し。
printfサイコー。
2005年06月15日
Javaその他のエントリー
2005年06月14日
2005年06月13日
2005年05月24日
2005年04月15日
2005年02月10日
2005年02月09日
2005年02月01日
2005年01月31日
2005年01月06日
2005年01月05日
2004年12月24日
2004年12月15日
2004年12月13日
2004年12月03日
2004年11月18日
2004年11月16日
2004年11月15日
2004年10月26日
2004年10月08日
2004年09月25日
2004年09月12日
2004年09月11日
2004年06月27日
2004年06月16日
2004年05月19日
2004年03月23日
2004年03月09日
2004年03月08日






