モバイルのもと

レコードストア

レコードストアはデータを保存したり、読み出したり出来るファイルシステムの様なものです。利用する際にはパッケージjavax.microedition.rms.*をインポートします。レコードストアは、そのやや独特な仕様から、単なるファイルの読み書きがしたいだけの利用者に混乱を招きます。

レコードストアは名前を持ったファイルで、データを追加していく事が出来ます。データを追加すると一意のIDが付与されます。IDを自分で決める事はできません。システム側が自動的に決定していきます。

レコードストアを新規作成したり、既存の物をオープンするには、RecordStoreクラスのopenRecordStore()メソッドで行います。このメソッドはstaticなので、RecordStoreの実体が無くても利用できます。

レコードストアに格納されるデータを、レコードと呼びます。レコードは任意の長さのバイナリを保存できます。

普通にデータを読み書きするだけなら、なんとも面倒臭い仕様なのですが、RecordComparator、RecordEnumeration、RecordFilterインターフェイスを利用する事によって、簡易データベースとして機能させる事が出来ます。使い方はMIDPのドキュメントにサンプルソースコード付きで詳しく載っていますので参考にして見てください。

 

ハイスコアの登録

ネット上には色々なサンプルがありますが、なぜか文字列の保存ばかりで、数値を保存するサンプルがありません。ためしにレコードストアにハイスコアを登録するコードを書いてみました。 単純コピペ用コードです。

private final String strRsHiscore = new String( "hiscore" );

  //...

//* ----------------------------------------------------------------------*/
public synchronized void saveScore(int score) {
  RecordStore rs = null;
  ByteArrayOutputStream baos = new ByteArrayOutputStream();
  DataOutputStream outputStream = new DataOutputStream(baos);

  try {
    rs = RecordStore.openRecordStore( strRsHiscore, true );
    outputStream.writeInt(score);

    byte[] b = baos.toByteArray();

    if( 0 == rs.getNumRecords() ) { // まだレコードが無い時は新しく作成
      rs.addRecord( b, 0, b.length );
    }
    else {
      rs.setRecord( 1, b, 0, b.length ); // レコードが存在するときはID1番に上書き
    }

    rs.closeRecordStore();
    outputStream = null;
    baos = null;
    rs = null;

  } catch (IOException ioe) {
    System.out.println(ioe.toString());
    ioe.printStackTrace();
  } catch (RecordStoreException rse) {
    System.out.println(rse.toString());
    rse.printStackTrace();
  }   
}

/* ----------------------------------------------------------------------*/
private synchronized int loadScore() {
  int score = 0;
    
  RecordStore rs = null;
  try {
    
    rs = RecordStore.openRecordStore( strRsHiscore, false );
    
    ByteArrayInputStream bais = new ByteArrayInputStream(rs.getRecord(1)); // ID1からデータを読み出す
    DataInputStream inputStream = new DataInputStream(bais);
        
    score = inputStream.readInt();

    rs.closeRecordStore();
    inputStream = null;
    bais = null;
    rs = null;

    return score;

  } catch (IOException ioe) {
    System.out.println(ioe.toString());
    ioe.printStackTrace();
  } catch (RecordStoreException rse) {
    System.out.println(rse.toString());
    rse.printStackTrace();
  } catch (Exception e) {
    System.out.println(e.toString());
  }
  return 0;
    
}

エラーが発生しました。(0B)が出る訳

色々試していたうちに気が付いたのですが、端末によっては書き込み速度が遅くて問題になることがあります。

例えば midlet.pauseApp() 関数内部で上記 saveScore() 関数を3回呼び出すと、次回midlet.startApp()時に以下の様な画面が出ます。

オープンアプリにエラーが発生しました。(0B)

具体的には以下の様なユースケースになります。

これはW51Hで発生し、W51SAでは発生しませんでした。

pauseApp()中に時間の掛かる処理を行うと、VMによって強制終了させられているようです。結果として次回再開するときには「既にアプリは死んでしまっている 」状態になっており、上記画面が表示されるようです。

これを避けるには「なるべく一回のopenRecordStoreで、全ての情報を書き込むようにする」、「情報はなるべく必要な時に保存し、pauseApp() / destroyApp()では書き込まない」等の工夫が必要です。


モバイルの素へ戻る MIDP Scrollトップへ戻る


Google
MIDP2.0 CLDC1.1 JSR WWW

Copyright 2007 Mobile no THU