ラベル Java の投稿を表示しています。 すべての投稿を表示
ラベル Java の投稿を表示しています。 すべての投稿を表示

2012-01-15

java.util.Scannerでコメント文をスキップさせたい

スクリプト言語のコメントをjava.util.Scannerに処理させたい。
commandA(myVar, 10)
; コメント
commandB(200)
区切りパターンにそれらしい正規表現を入れたら上手くいった。
scanner.useDelimiter("(\\s|;.*(\r|\n|\r\n))+");

java.util.Scannerでスクリプトの命令文を分割したい

スクリプトの命令文「command(myVar, 100)」を
"command" "(" "myVar" "," "100" ")"
の6つに分割したい。カッコもコンマもスクリプトの要素として意味があるので、分割結果として欲しい。が、java.util.Scannerをそのまま使うと
"command(myVar," "100)"
の2つに分割されてしまう。Scannerにテキストの区切りパターン(正規表現)を設定することは可能だが、カッコやカンマを区切りパターンに追加すると、今度は分割結果から無くなってしまう。
"command" "myVar" "100"
そんな場合は、Scanner#findInLine(Pattern pattern)で、さらに細かく分割すれば良いようだ。
Pattern pattern = Pattern.compile("[(),]|[a-zA-Z0-9]+");
Scanner scanner = new Scanner("command(myVar, 100)");
while (scanner.hasNext()) {
    for (;;) {
        String token = scanner.findInLine(pattern);
        if (token == null) {
            break;
        }
        System.out.println(token);
    }
}
以下の結果を得ることが出来た。
command
(
myVar
,
100
)

2011-04-02

Google App EngineにTwitter BOTを載せる

3時間に1回、ランダムなテキストをツイートする単純なBOTを作ってみた(@raulnylmsという名前で公開、2015年時点で削除済み)。
Twitterへのアクセスが必要な部分は、Twitter4Jのおかげで簡単に作れた。これはすごい便利だった。
「1時間に1回ツイートする」スケジューリングは、Google App Engineが提供するcronを使って、こちらも簡単に実現できた。設定ファイルに"every 1 hours"とか書けば済んだ。
問題はGoogle App Engineのデータストア(Bigtable)で、ファイルの読み書きとも従来のデータベースアクセスとも勝手が違うので、かなり戸惑った。あと、Java版だと、データを一度に大量アップロードする機能は付いてない...。まあ、今回はGoogle App EngineのFAQページに載ってたサンプルコードを参考に、アップロード機能を自作して済ませた。

2011-01-04

CASL IIシミュレータ作成時に使おうとして諦めたJava APIいろいろ

java.nio.ByteBuffer。アセンブラが出力するオブジェクトファイルの読み書きに使おうとしたのだけれど、単純な1入力1出力の処理だったので、昔ながらのjava.io.DataInputStream/DataOutputStreamで事足りてしまった。Enumに並んで完璧主義が光るクラスではある。
java.io.Console。あるいはjava.lang.System.console()。名前通りコマンドライン入出力に便利な機能が揃っているのだが、今回は単純なテキスト出力処理がほとんどだったので、使う機会がなかった。
java.util.Scanner。DeveloperWorksの記事で紹介されているように、数値と文字が記述されたテキストの読み込みは、これで大体まかなえるはずなのだが...。CASL IIの仕様を読んでみると、数値やコメントの扱いに独特の解釈があって、結局、構文解析処理は全部自作した。

2010-05-05

RhinoでJavaのCanvasに描画したいと思った

さすがに描画処理(paintメソッド)のリスナーインタフェースは見当たらなかったので、Javaのソースファイルに以下のようなクラスを書いて、コンパイルしておく。
/** 自作キャンバス */
public class MyCanvas extends JPanel {
    /** オフスクリーンバッファに描画するためのオブジェクト */
    private Graphics backGraphics;
    /** キャンバスを作成する */
    public MyCanvas() {
        super(false);  // JPanel提供のダブルバッファリングは使わない
    }
    /** オフスクリーンバッファに描画するためのオブジェクトを返す */
    public Graphics getBackGraphics() {
        return backGraphics;
    }
    //...以下略
    // backGraphicsを初期化する処理が必要
}
後は、Rhinoのスクリプトでオフスクリーンバッファへ描画してから repaint() で自作キャンバスを再描画する。

上のソースはbackGraphicsを初期化する処理が抜けていて、今回は古いやり方に従って描画メソッド(JPanelなのでpaintComponentメソッド)が初めて呼び出された時だけcreateImage()でオフスクリーンバッファ(と、そのGraphicsオブジェクト)を作成するようにした。
Javaは「Compatibleな」オフスクリーンバッファを作るメソッド、というのが幾つもあるのだけれど、いまいち最適な使い方が分からない。

2008-08-09

モノクロアニメをdrawLine()で描画する

「へらへらアニメ」を表示するアプレットを作ろうとした時に念頭にあったのは、できるだけ沢山のパソコン上で楽しめるようにしたいということで、当時はWin9x+MSJavaという組合せも考慮する必要があった。これは、Java1.1.x互換なコードを書く必要があることを意味する。
AWTの解説書やWebサイトで調べてみると、ビットやバイトで構成されたイメージでアニメーションをやりたい場合、MemoryImageSourceを使うのが手堅いやり方のようだった。さらにJava APIのドキュメントを読んでみて、MemoryImageSourceでやるしかないのだと確信した。
そこで、実際にアプレットを作って動かしてみた。

なんか変だ。

アニメーション自体の速度がGIFアニメよりも若干まずい点は、まあ、そういうものだと諦めるとしても、定期的に極端に低速になるというか、何かがロックされているかのごとくカクカクした動きになることがあって、このままだとソフトウェアの不具合だとみなされてしまいかねない動きだったので、さすがに公開はしなかった。
注意しておくと、AWTの解説書もWebサイトもJava APIドキュメントも、全く落ち度はない。異なるスペックのパソコンを借りたりして調べた限りでは、どうもWin9xがプリインストールされたマシンをそのまま使い続けているような古い環境だと上記の問題が起こるようだった。
困ったことに、調べたり人に聞いたりしてもこの問題の原因は分からなかった。
あれこれ変な方法を試したり失敗したりを繰り返した末に、一番あり得ない手段だと思っていた、drawLine()で左から右へ線を何度も引くやり方でイメージを描画することにした。すると、確かに速度がまずくなる瞬間は発生するものの、MemoryImageSourceを使った時よりはずっとマシになっていた。
結局、drawLine()で描画する方を公開することにした。それから忙しくなったりパソコンが変わったりしているうちに、MemoryImageSourceを使った方のソースはどこかに行ってしまった。
現在公開されている「へらへらアニメ」用のアプレットはdrawLine()で描画されていて、今でも問題なく動いている。が、いまだにこのやり方が本当に良かったのかどうか疑問に思うことがある。

2008-08-03

文字エンコーディング名かCharsetか

Javaでテキスト処理をする時に、
Reader createReader(String fileName, String encoding)
なメソッドを書いていて思った。
最近はjava.nio.charset.Charsetがあるので、以下のようにも書ける。
Reader createReader(String fileName, Charset charset)
後者はちゃんと目的に特化したクラスを使っているので、前者よりも手堅い印象がある。特に、文字エンコーディング名がCharsetに変換される時の例外処理をcreateReader()が抱えなくて済むという安心感がある。
一方で、createReader()を使う側としては、前者のオーバーライドも用意しておいてくれた方が便利でうれしい。

似たような話は、以下のような場合にも出てくる。
  • ファイルパスかjava.io.Fileか
  • URLかjava.net.URLか(URIの場合も同様)
実装する前にちょっと考えないと、チェック処理の責任が色んなメソッドに波及して面倒なんだよね...。

いつの間に文字列は汎用データ型みたいになったんだろう。
Win32 APIをC言語から利用する場合、32ビット整数が色んなオブジェクトやら何やらを表していて(ハンドルとかいった)、持ち運び易い反面、危なっかしいところがあった。(Win32 APIを使うスクリプト言語まで同様のやり方でリソース管理するようユーザに要求する流れが現れたことで、問題はさらにややこしくなる...)