Mobile:NEWS 2003年12月12日 03:07 PM 更新

BREW プログラミング入門(8)
ファイルを操作してみよう(3/3)


前のページ

ファイルからの読み込み

 それでは、いよいよファイルからデータを読み込んでみましょう。BREWでファイルを読み込む場合、ほとんどの場合即時に読み込む事ができますが、ファイルの読み込み自体はノンブロッキングであると記述されています。

 ノンブロッキングとはファイルからの読み込みが完全に終わる前に次の処理に実行が移ってしまう方式を指します。また、ブロッキングはその逆でファイルから完全にデータが読み込まれるまで、実行が 次に移ることはありません。BREW APIリファレンスにはIFILE_Readはノンブロッキングであると記述されているのですが、実際のところはブロッキング動作を行っているようです。

 このあたりは、IAStreamインタフェースを使用してアクセスするインタフェースがほかに存在した場合に、処理を抽象的に行えるように、インタフェースはノンブロッキングであると定義されているのかもしれません。IFileインタフェースとして使用する分にはブロッキングであると考えていいようですが、確証はできていません。少なくともBREW SDKに付属してくるサンプルは、ブロッキングとして記述されています。

 まずは、ノンブロッキングでないと仮定した場合の読み込み方法を示します。以下にファイルをオープンしたのち、ファイルからデータを読み込みバッファに格納するコードを示します。

IShell*  shell = app->a.m_pIShell;
IFileMgr*  filemgr;
IFile*  file;
char  buffer[128];
int  size;
// IFileMgr インタフェースの作成
ISHELL_CreateInstance(shell,AEECLSID_FILEMGR,(void*)&filemgr);
// ファイルの新規オープン
file = IFILEMGR_OpenFile(filemgr,"sample.txt",_OFM_READ);
// ファイルからのデータの読み込み
size = IFILE_Read(file,buffer,sizeof(buffer) - 1);
// 読み込んだデータの出力
buffer[size] = '\0';
DBGPRINTF("read : %s",buffer);
// ファイルのクローズ
IFILE_Release(file);
// IFileMgr インタフェースの破棄
IFILEMGR_Release(filemgr);

※エラー処理はしていません。実際のコーディングではより強固なエラー処理をするべきです。

 次に、ノンブロッキングであることを意識した読み込み方法を示します。以下のコードは上記のコードと全く同じ内容の処理を行うコードです。

// Filesystem アプレット構造体
typedef struct FilesystemApplet {
  AEEApplet  a;
  // 確保したインタフェースオブジェクトを保持するメンバ
  IFileMgr*  filemgr;
  IFile*  file;
  char  buffer[128];
} FilesystemApplet;

static void ReadCallback(FilesystemApplet* app)
{
  int  size;
  // ファイルからのデータの読み込み
  size = IFILE_Read(app->file,app->buffer,sizeof(app->buffer) - 1);
  // 結果の判別
  switch (size) {
    case AEE_STREAM_WOULDBLOCK:  // ブロッキング中
      // コールバックの登録
      //
      // AEE_STREAM_WOULDBLOCK は IAStream で定義されていますが、
      // IFile では発生しないようです。
      IFILE_Readable(app->file,(PFNNOTIFY)ReadCallback,app);
      break;
    case 0:  // 失敗
      // ファイルのクローズ
      IFILE_Release(app->file);
      // IFileMgr インタフェースの破棄
      IFILEMGR_Release(app->filemgr);
      break;
    default:  // その他
      if (size > 0) {
        // 読み込んだデータの出力
        app->buffer[size] = '\0';
        DBGPRINTF("read : %s",app->buffer);
        // ファイルのクローズ
        IFILE_Release(app->file);
        // IFileMgr インタフェースの破棄
        IFILEMGR_Release(app->filemgr);
      }
      break;
  }
  return;
}
// ここから、読み込み処理
IShell*  shell = app->a.m_pIShell;
// IFileMgr インタフェースの作成
ISHELL_CreateInstance(shell,AEECLSID_FILEMGR,(void*)&app->filemgr);
// ファイルの新規オープン
app->file = IFILEMGR_OpenFile(app->filemgr,"sample.txt",_OFM_READ);
// コールバックの登録
IFILE_Readable(app->file,(PFNNOTIFY)ReadCallback,app);

 上記コードでは、実際の読み込みをコールバック関数内で行っています。IFILE_Readable関数を使用すると、ファイルからデータが実際に読み込めるタイミングになるまで読み込み処理をペンディングできます。

 この方法は、ネットワークからのデータの読み込みにも応用できます。コールバック型になるため、インタフェースの破棄のタイミングの管理や途中でユーザの操作が行われる可能性があるなど、処理の流れの管理がややこしくなると言う欠点があります。しかし、ファイルからの読み込みに時間がかかる環境などではCPUの実行をストップしないですむため、こちらの実装のほうが適している場合もあります。

 実機にはウォッチドッグタイマというものが存在し、CPUを長時間占領されつづけられたときに、致命的なエラーが発生したとみなして実機を再起動してしまいます。ファイルからの読み込みをブロッキングで行い、余りにも長い時間がかかってしまうと、このウォッチドッグタイマに捕まってしまう危険性があります。これを避けるためにもノンブロッキングで読み込むことには意味があります。以下にノンブロッキングでの読み込み処理の流れをフローチャートにまとめておきます。


ノンブロッキング処理の流れ

 ところで、上記コードはIFILE_Read関数が一度で完全にデータを読み込めることを仮定しています。もし、IFILE_Read関数が希望したバイト数を読み込めなかった場合、さらにIFILE_Readable関数を使用してコールバックを登録する必要があるかもしれません。

◆ファイルへの書き込み

 次に、ファイルへの書き込みを行ってみましょう。読み込みの時とは違い、ファイルへの書き込みはノンブロッキングではありません。こちらの処理は簡単な内容になります。以下に、新規にファイルをオープンしたのち、バッファからファイルにデータを書き出すコードを示します。

IShell*  shell = app->a.m_pIShell;
IFileMgr*  filemgr;
IFile*  file;
char  buffer[] = "If you didn't know about the FRAMEWORK for BREW,"
          " the development of your products will be in the deadline.";
// IFileMgr インターフェースの作成
ISHELL_CreateInstance(shell,AEECLSID_FILEMGR,(void*)&filemgr);
// ファイルの新規オープン
file = IFILEMGR_OpenFile(filemgr,"sample.txt",_OFM_CREATE);
// ファイルへのデータの書き込み
IFILE_Write(file,buffer,sizeof(buffer) - 1);
// ファイルのクローズ
IFILE_Release(file);
// IFileMgr インターフェースの破棄
IFILEMGR_Release(filemgr);

※エラー処理はしていません。実際のコーディングではより強固なエラー処理をするべきです。

 IFILE_Write関数は書き込みが成功した場合、書き込んだバイト数が、また何らかの原因で失敗した場合、0を戻り値として返すようです。BREW APIリファレンスには確実に書き込みが一度で終わるとは記述されていませんので、書き込みたいデータのサイズが書き込まれたデータのサイズよりも大きい場合は、IFILE_Write関数をもう一度呼び出すなどの処理が必要かもしれません。いずれにしても、あまりにも大きいデータを書き込もうとして実機のウォッチドッグタイマに捕まってしまわないようにしなければなりません。

まとめ

 今回はファイルシステムの解説をした後、ディレクトリの操作方法やファイルの操作方法について解説しました。BREWには非常に柔軟なファイルシステムが存在し、いろいろと面白いことができそうです。また、実装依存ではありますが共有ディレクトリが使用できるなどアプリ間でファイルを共有する仕組みも用意されています。

 現在の実機では、アプリフォルダの容量に限界があり大量にファイルを使用するようなことは事実上できないかもしれませんが、今後容量が増えて環境が強化されることを期待しています。

※今回の記事のソースコードは、ソフィア・クレイドル のサイトからダウンロードできます。

著者紹介
堀口淳史:ソフィア・クレイドル研究開発部チーフ ソフトウェアアーキテクト。ソフィア・クレイドルは、2002年2月京都市にて、無限の可能性を秘めたソフトウェア職人たちが楽しく集い、自ずと自己実現が達成される場になることを目指して創業。在籍スタッフの平均年齢は20代前半と若いが、その大半がプログラミング歴10年以上とそのプロフェッショナリティは極めて濃い集団である。

 これまでにBREW用アプリケーションフレームワークケータイJavaプログラム圧縮技術ケータイJavaブラウザ技術、ケータイメッセンジャー技術などを総合的に研究開発し、「高品質な共通プラットフォーム」の実現を目指してきた。

ご感想、ご質問はこちら(zdnet-contact@s-cradle.com)まで。



関連記事
▼ BREW プログラミング入門(7):さらに描画のおはなし
前回はリソースファイルの作成方法と、リソースからビットマップを取得して画面に表示する方法を解説しました。今回はもう少し描画関係の話をしたいと思います。

▼ BREW プログラミング入門(6):ビットマップを描画してみよう
前回はイベント処理について解説しました。今回はファイルやリソースに関する事柄とビットマップやイメージの描画について解説します。

▼ BREW プログラミング入門(5):イベント処理って何だ?
前回は文字列の扱い方について解説しました。今回はBREWのイベント処理について学びます。

▼ BREW プログラミング入門(4):BREW の文字列について知ろう
前回は画面描画のAPI、インタフェースやアプレット構造体についての理解を深めました。今回は文字列の扱い方について解説します。

▼ BREW プログラミング入門(3):画面に描画をしてみよう
前回の連載では、HelloWorldアプレットを作成することで、BREWアプリケーションのおおまかな構造について学びました。今回は画面描画のAPIについて詳しく説明するとともに、インタフェースやアプレット構造体についての理解を深めます。

▼ BREW プログラミング入門(2):“HelloWorld”プログラムを作ろう
前回の連載では、BREW SDK 2.1をインストールするところまで解説しました。今回は実際にソースコードを書き、BREWエミュレータで動かしてみましょう。画面に "Hello World" と表示する簡単なBREWアプリを作成します。

▼ BREW プログラミング入門(1):BREW SDKをインストールしよう
本連載は、BREWに興味がありプログラミングを始めてみたいけれど、どこから手をつけてよいか分からない方々を対象に、ステップ・バイ・ステップでBREWプログラミングを行う方法を解説していきます

▼ Qualcomm、携帯電話向けプラットフォーム「BREW」発表──au端末に搭載
▼ “携帯電話のOS”を目指すBREW──国内でも1号機
▼ BREWとは何か?──Javaとの違い
▼ 連載バックナンバー

[堀口淳史, ITmedia]

Copyright © ITmedia, Inc. All Rights Reserved.

前のページ | 3/3 | 最初のページ



モバイルショップ

最新CPU搭載パソコンはドスパラで!!
第3世代インテルCoreプロセッサー搭載PC ドスパラはスピード出荷でお届けします!!

最新スペック搭載ゲームパソコン
高性能でゲームが快適なのは
ドスパラゲームパソコンガレリア!