ホーム > デベロッパ > SophiaFramework > BREW C++ 逆引きコード集

BREW C++ プログラミング 逆引きコード集 : ファイル

C++ で作成されたBREW アプリで、ファイルの読み書き・移動・コピー・削除などを行う方法です。
SophiaFramework を用いています。

BREW コールバック関数の登録と呼び出し(JPEG 画像データを読み込んで表示する方法)

BREW ネイティブのコールバック関数を登録し、呼び出すためのサンプルコードです。

ファイルストレージまたはメモリストレージに保存された JPEG 画像データを読み込んで表示するコードを以下に記します。

BREW の仕様では、JPEG 画像データの表示処理は、ファイルストレージまたはメモリストレージに保存された JPEG 画像データの読み込みが完了したときに呼び出されるコールバック関数内に記述する必要があります。

ファイルストレージまたはメモリストレージに保存された JPEG 画像データを読み込むためのストリームは、 SFBImage::SetStream() 関数を使って設定します。

コールバック関数は SFBImage::Notify() 関数を使って登録します。

なお、コールバック関数を登録する SFBImage 型のインスタンス変数は jpegreader クラスの変数として登録します。メンバ関数などローカル変数として登録すると、スマートポインターで管理されるため変数スコープから外れたときに、メモリは自動的に解放され、コールバック関数が呼び出されません。

また、コールバック関数の実体は、ダミーのコールバック関数内から呼び出されます。コールバック関数の登録では、ダミーのコールバック関数を登録します。

■クラスの定義

SFMTYPEDEFCLASS(jpegreader)
class  : public SFYApplication {
    SFMSEALCOPY(jpegreader)
private:
    SFBImageSmp _image;
public:
    static SFCInvokerPtr Factory(Void);
private:
    explicit jpegreader(Void) static_throws;
    virtual ~jpegreader(Void);
    SFCError LoadImage(SFXPathConstRef path);
    SFCError ExampleDirectFile(SFXFilePtr file); 
    SFCError ExampleThroughMemory(SFXFilePtr file, UInt32 size);
    XANDLER_DECLARE_BOOLEVENT(OnKey)
   
    // コールバック関数の実体
    Void OnImage(Void);  
    // ダミーのコールバック関数
    friend Void read_finished(VoidPtr, IImage*, AEEImageInfo*, SIntN);  
};

※注意:
1.JPEG 画像データを読み込む変数 _image は、クラス変数として定義します。JPEG 画像データを読み込むためのメンバ関数 LoadImage() 内のローカル変数として定義すると、JPEG 画像データの読み込み完了時に自動的に解放されるため、JPEG 画像を表示するためのダミーのコールバック関数 read_finished() が呼び出されません。

2.JPEG 画像を表示するためのダミーのコールバック関数 read_finished()は、friend 関数として定義します。

3.JPEG 画像を表示する実際の処理は、jpegreader::OnImage() 関数に記述します。このメンバ関数は、ダミーのコールバック関数 read_finished() から呼び出されます。

■クラスの実装

// パスから JPEG 画像データを読み込む
SFCError jpegreader::LoadImage(SFXPathConstRef path)
{
    SFXFile   file;
    UInt32    size;
    SFCError  error(SFERR_NO_ERROR);

    if ((_image = SFBImage::NewInstance(AEECLSID_JPEG, &error)) != null) {

        if ((error = file.OpenReadOnly(path)) == SFERR_NO_ERROR) {

            if ((error = file.GetSize(path, &size)) == SFERR_NO_ERROR) {

                // ファイルストレージから JPEG 画像を読み込む場合
                // ExampleDirectFile(&file);  

                // メモリストレージから JPEG 画像を読み込む場合
                ExampleThroughMemory(&file, size);
             }
        }
    }
    return error;
}

// ファイルストレージから JPEG 画像データを読み込む
SFCError jpegreader::ExampleDirectFile(SFXFilePtr file)
{
    // ダミーのコールバック関数を登録する
    _image->Notify((PFNIMAGEINFO)read_finished, this);

    // ファイルストレージのストリームを設定する
    return _image->SetStream(*file);
}

// メモリストレージから JPEG 画像データを読み込む
SFCError jpegreader::ExampleThroughMemory(SFXFilePtr file, UInt32 size)
{
    SFXBuffer  buffer;
    VoidPtr    ptr;
    SFXMemory  memory;
    SFCError   error(SFERR_NO_ERROR);

    if (size > 0) {

        if ((error = buffer.SetSize(size)) == SFERR_NO_ERROR) {

            ptr = buffer.Detach();

            if ((error = file->Read(ptr, &size)) == SFERR_NO_ERROR) {

                if ((error = buffer.Attach(ptr, size)) ==SFERR_NO_ERROR) {

                    if ((error = memory.Open(buffer)) == SFERR_NO_ERROR) {

                        // ダミーのコールバック関数を登録する
                        _image->Notify((PFNIMAGEINFO)read_finished, this);

                        // メモリストレージのストリームを設定する
                        error = _image->SetStream(memory);
                    }
                }
            }
        }
    }
    else {
        error = SFERR_FAILED;
    }
    return error;
}

// 実際のコールバック関数(実体:  JPEG 画像を描画する)
Void jpegreader::OnImage(Void)
{
    SFXRectangle  rx;
    AEEImageInfo  info;

    rx.Set(GetLocalBound());

    _image->GetInfo(&info);

    //  JPEG 画像を描画する
    _image->Draw((rx.GetWidth()-info.cx)/2, (rx.GetHeight()-info.cy)/2);

    return;
}

// ダミーのコールバック関数(PFNIMAGEINFO 型)
Void read_finished(VoidPtr reference, IImage* /* image*/, AEEImageInfo* /* info*/, SIntN /* error*/)
{
    // 実際のコールバック関数を呼び出す
    static_cast<jpegreaderPtr>(reference)->OnImage();

    return;
}

※注意:
4.JPEG 画像表示処理の実体は、ダミーのコールバック関数 read_finished() から呼び出される実際のコールバック関数 jpegreader::OnImage() 内に実装します。

5.JPEG 画像データを読み込むためのファイルストレージまたはメモリストレージを SFBImage::SetStream() 関数を使って設定し、SFBImage::Notify() 関数を使ってダミーのコールバック関数 read_finished() を登録します。

サンプルコードダウンロード( jpegreader.zip: 99.7kb )

□関連情報:BREW FAQ : JPEG 形式で保存した画像ファイルを読み込むには

      

親ディレクトリを取得する

親ディレクトリを取得するには SFXPath::GetParentPath もしくは SFXPath::GetParent を使用します。
SFXPath::GetParentPathSFXPath::GetParent の違いは、取得する値が SFXPathSFXAnsiString の違いです。

SFXPath path1("/dir1/dir2/data.txt");
SFXPath path2;
SFXAnsiString string;

// path2 は "/dir1/dir2/"、path1 は変化なし
path2 = path1.GetParentPath();

// 文字列を返すバージョン
string = path1.GetParent();
      

ディレクトリの容量を取得する

ディレクトリの容量を調べるには、SFXDirectory::DeviceTotalSpace 関数を使用します。

UInt32 space;

SFXDirectory::DeviceTotalSpace(&space); // space に容量が入る
      

テンポラリ ファイル名を取得する

テンポラリ ファイル名を取得するには、SFXFile::GetTemporaryPathを使用します。

SFXPath path;
SFXPath parentPath;

parentPath.Set(SFXAnsiString("/"));

SFXFile::GetTemporaryPath(parentPath, &path); // path には "/sfx7182CBD4.tmp" のようなファイル名が入る
      

一意なファイル名を取得する

一意なファイル名を取得するには、SFXFile::GetUniquePath を使用します。

SFXPath path;
SFXPath parentPath;

parentPath.Set(SFXAnsiString("/"));

SFXFile::GetUniquePath(parentPath, "data", ".txt", &path);  // path には "/data829AE714.txt" のようなファイル名が入る
      

デバイス空き容量を取得する

ファイル・ディレクトリのデバイス空き容量を調べるには、SFXFile::DeviceFreeSpace 関数を使用します。

UInt32 space;

SFXFile::DeviceFreeSpace(&space); // space に空き容量が入る
      

ファイルが読み込み専用か判定する

ファイル・ディレクトリの存在を調べるには、SFXFile::IsReadOnly関数を使用します。

Bool b;

// IsReadOnly 関数の戻り値はエラー値
SFXFile::IsReadOnly(SFXPath("/dir1/data.txt"), &b);

if (b) {
    // ファイルが読み込み専用の場合

}
      

ファイルの終端を検知する

バージョン 4.0 以降

ファイルからデータを読み取るストリームでファイルの終端を検知するには、
SFXStreamReader::Ends 関数を使用します。

以下のコードは、ファイルから終端に達するまで1文字ずつ読み込み、表示します。

SFXFile file;
SFXBinaryStreamReader reader;

if (file.OpenReadOnly(SFXPath("/data.txt")) == SFERR_NO_ERROR) {
    // ファイルのオープンに成功したなら
    UInt08 c;
    file.GetStreamReader(10, &reader);

    while (!reader.Ends()) { // ファイルの終端に到達するまで
        if (reader.GetReadableSize() == 0) {
            reader.Fetch();
        }
        reader >> c;      // 1文字読み込み
        TRACE("%c", c);   // 表示
    }
    file.Close();
}

バージョン 3.0

ファイルストリームでファイルの終端を検知するには、
SFUFileStream::IsEOS 関数を使用します。

以下のコードは、ファイルから終端に達するまで1文字ずつ読み込み、表示します。

SFUFileStream fstream;

if (fstream.Open("/data.txt", _OFM_READ) == SFERR_NO_ERROR) {
    // ファイルのオープンに成功したなら
    AChar c;

    while (!fstream.IsEOS()) { // ファイルの終端に到達するまで
        fstream >> c;      // 1文字読み込み
        TRACE("%c", c);    // 表示
    }
    fstream.Close();
}

参照 SFXFile::OpenReadOnly | SFXFile::GetStreamReader |
SFXStreamReader::GetReadableSize | SFXStreamReader::Fetch

      

ファイルをコピーする

BREW にはファイルをコピーする関数はありません。
以下のように、ファイルを読みとり、それを書き込むことでコピーします。

バージョン 4.0 以降

// src.txt を dst.txt にコピー
SFXFile fin;
SFXFile fout;
SFXBinaryStreamReader reader;
SFXBinaryStreamWriter writer;
SFXBuffer buffer;

if (fin.OpenReadOnly(SFXPath("/src.txt")) == SFERR_NO_ERROR) {
    // 読み込みファイルのオープンに成功した
    if (fout.OpenReadWrite(SFXPath("/dst.txt")) == SFERR_NO_ERROR) {
        // 書き込みファイルのオープンに成功した

        fin.GetStreamReader(1024, &reader);
        fout.GetStreamWriter(1024, &writer);

        UInt08 c;
        while (!reader.Ends()) { // ファイルの終端にくるまで
            buffer.SetSize(reader.GetReadableSize());
            reader.Fetch();
            reader.Read(&buffer); // 読み込み
            writer.Write(buffer); // 書き込み
            writer.Flush();
        }
        fout.Close();
    }
    fin.Close();
}

バージョン 3.0

// src.txt を dst.txt にコピー
SFUFileStream fin;
SFUFileStream fout;

if (fin.Open("/src.txt", _OFM_READ) == SFERR_NO_ERROR) {
    // 読み込みファイルのオープンに成功した
    if (fout.Open("/dst.txt", _OFM_CREATE) == SFERR_NO_ERROR) {
        // 書き込みファイルのオープンに成功した

        AChar c;
        while (!fin.IsEOS()) {  // ファイルの終端にくるまで
            fin >> c;     // 1文字読み込み
            fout << c;    // 1文字書き込む
        }
        fout.Close();
    }
    fin.Close();
}

参照 SFXFile::OpenReadOnly | SFXFile::OpenReadWrite |
SFXFile::GetStreamReader | SFXFile::GetStreamWriter |
SFXStreamReader::GetReadableSize | SFXStreamReader::Fetch
SFXStreamReader::Read | SFXStreamWriter::Write
SFXStreamWriter::Flush

      

ファイルを移動する(ファイル名変更)

バージョン 4.0 以降

ファイルを移動するには、SFXFile::Rename 関数を使用します。

// dir1 ディレクトリにある data.txt を dir2 に移動する
if (SFXFile::Rename(SFXPath("/dir1/data.txt"), SFXPath("/dir2/data.txt"))
    == SFERR_NO_ERROR) {
    // 成功したなら
    ...
}

// dir1 ディレクトリにある data.txt を file.txt に変更する
if (SFXFile::Rename(SFXPath("/dir1/data.txt"), SFXPath("/dir1/file.txt"))
    == SFERR_NO_ERROR) {
    // 成功したなら
    ...
}

バージョン 3.0

ファイルやディレクトリを移動するには、SFBFileMgr::Rename 関数を使用します。

SFBFileMgrSmp fileMgr = SFBFileMgr::NewInstance();

// dir1 ディレクトリにある data.txt を dir2 に移動する
if (fileMgr->Rename("/dir1/data.txt", "/dir2/data.txt") == SFERR_NO_ERROR) {
    // 成功したなら
    ...
}

// dir1 ディレクトリにある data.txt を file.txt に変更する
if (fileMgr->Rename("/dir1/data.txt", "/dir1/file.txt") == SFERR_NO_ERROR) {
    // 成功したなら
    ...
}

参照 SFXFile::Rename | SFBFileMgr::NewInstance | SFBFileMgr::Rename

      

ファイルを削除する

バージョン 4.0 以降

ファイルを削除するには、SFXFile::Remove 関数を使用します。

// dir ディレクトリ内のdata.txt を削除
if (SFXFile::Remove(SFXPath("/dir/data.txt")) == SFERR_NO_ERROR) {
    // 成功したなら
}

バージョン 3.0

ファイルを削除するには、SFBFileMgr::Remove 関数を使用します。

SFBFileMgrSmp fileMgr = SFBFileMgr::NewInstance();

// dir ディレクトリ内のdata.txt を削除
if (fileMgr->Remove("/dir/data.txt") == SFERR_NO_ERROR) {
    // 成功したなら
}

参照 SFXFile::Remove | SFBFileMgr::NewInstance | SFBFileMgr::Remove

      

ディレクトリを削除する

バージョン 4.0 以降

ディレクトリを削除するには、SFXDirectory::Remove 関数を使用します。

第2引数を true にすると中身を再帰的に削除します。

// data ディレクトリの中の dir ディレクトリの削除 (中身も削除)
if (SFXDirectory::Remove(SFXPath("/data/dir/"), true) == SFERR_NO_ERROR) {
    // 成功した場合
}

バージョン 3.0

ディレクトリを削除するには、SFBFileMgr::RmDir 関数を使用します。

ディレクトリの中が空でない場合は失敗します。

SFBFileMgrSmp fileMgr = SFBFileMgr::NewInstance();

// data ディレクトリの中の dir ディレクトリの削除
if (fileMgr->RmDir("/data/dir/") == SFERR_NO_ERROR) {
    // 成功した場合
}

参照 SFXDirectory::Remove | SFBFileMgr::NewInstance | SFBFileMgr::RmDir

      

ファイルの作成日を取得する

バージョン 4.0 以降

ファイルの作成日を取得するには、SFXFile::GetCreateDate 関数を使用します。

SFXDate date;

SFXFile::GetCreateDate(SFXPath("/data/data1.txt"), &date);

バージョン 3.0

ファイルの作成日を取得するには、SFBFileMgr::GetInfo 関数を使用します。

SFBFileMgrSmp fileMgr = SFBFileMgr::NewInstance();
FileInfo info = {0};

fileMgr->GetInfo("/data/data1.txt", &info);   // ファイルの情報を取得する

// ファイル作成日(1980 年1 月6 日00:00:00 グリニッジ標準時からの経過時間)
UInt32 fileTime = info.dwCreationDate;

SFXDate date(info.dwCreationDate);    // SFXDate 形式に変換

参照 SFXFile::GetCreateDate | SFBFileMgr::NewInstance | SFBFileMgr::GetInfo

      

ファイルサイズを取得する

バージョン 4.0 以降

ファイルのサイズを取得するには、SFXFile::GetSize 関数を使用します。

UInt32 size;

// size にファイルサイズが入る
SFXFile::GetSize(SFXPath("/data/data1.txt"), &size);

バージョン 3.0

ファイルのサイズを取得するには、SFBFileMgr::GetInfo 関数を使用します。

SFBFileMgrSmp fileMgr = SFBFileMgr::NewInstance();
FileInfo info = {0};

fileMgr->GetInfo("/data/data1.txt", &info);   // ファイルの情報を取得する

UInt32 size = info.dwSize;   // size にファイルサイズが入る

参照 SFXFile::GetSize | SFBFileMgr::NewInstance | SFBFileMgr::GetInfo

      

あるディレクトリにあるファイルを列挙する

バージョン 4.0 以降

あるディレクトリにあるファイルを列挙するには、ファイル列挙子と
ディレクトリ列挙子を使用します。

SFXDirectory::Enumerator etor;

// ファイル列挙子の取得
SFXDirectory::GetFileEnumerator(SFXPath("/dir1/"), &etor);
// SFXDirectory::GetDirectoryEnumerator でディレクトリ列挙子の取得

// ファイルの情報を取得する
while (etor.HasNext()) {
    // path にはファイル名が入る
    SFXPath path = etor.GetNext();

}

サブディレクトリも列挙する場合は以下のような再帰関数を定義します。

Void EnumerateDirectory(SFXPath path) {
    SFXDirectory::Enumerator etor;

    // ファイル列挙子の取得
    SFXDirectory::GetFileEnumerator(path, &etor);

    while (etor.HasNext()) { // 各ファイルについて
        // filename にはファイル名が入る
        SFXPath filename = etor.GetNext();

    }

    // ディレクトリ列挙子の取得
    SFXDirectory::GetDirectoryEnumerator(path, &etor);

    while (etor.HasNext()) { // 各ディレクトリについて
        EnumerateDirectory(etor.GetNext());

    }
}

使用例

EnumerateDirectory(SFXPath("/dir1/"));  // dir1 以下のすべてのファイルを列挙

バージョン 3.0

あるディレクトリにあるファイルを列挙するには、SFBFileMgr::EnumInit 関数と
SFBFileMgr::EnumNext 関数を使用します。

SFBFileMgrSmp fileMgr = SFBFileMgr::NewInstance();
FileInfo info = {0};

// dir1/ ディレクトリのファイルを列挙するための初期化を行う
// 2つめの引数は false ならファイル列挙、true ならディレクトリ列挙
if (fileMgr->EnumInit("/dir1/", false) == SFERR_NO_ERROR) {

    // ファイルの情報を取得する
    while (fileMgr->EnumNext(&info)) {
        // fileName にはファイル名が入る
        SFXAnsiString fileName = info.szName;

    }
}

サブディレクトリも列挙する場合は以下のような再帰関数を定義します。

Void EnumerateDirectory(SFXAnsiString dir_name) {
    SFBFileMgrSmp   fileMgr = SFBFileMgr::NewInstance();
    FileInfo        info    = {0};

    // ファイルを列挙するための初期化を行う
    if (fileMgr->EnumInit(dir_name, false) == SFERR_NO_ERROR) {

        // 次のファイルの情報を取得する
        while (fileMgr->EnumNext(&info)) {
            // fileName にはファイル名が入る
            SFXAnsiString fileName = info.szName;

        }
    }

    // ディレクトリを列挙するための初期化を行う
    if (fileMgr->EnumInit(dir_name, true) == SFERR_NO_ERROR) {

        // 次のディレクトリの情報を取得する
        while (fileMgr->EnumNext(&info)) {
            // fileName にはディレクトリ名が入る
            SFXAnsiString dirName = info.szName;

            // 再帰呼び出し
            EnumerateDirectory(dirName);
        }
    }
}

使用例

EnumerateDirectory("/dir1/");  // dir1 以下のすべてのファイルを列挙

参照 SFXDirectory::GetFileEnumerator | SFXDirectory::GetDirectoryEnumerator |
SFBFileMgr::EnumInit | SFBFileMgr::EnumNext

      

ファイルから読み込みを行う

バージョン 4.0 以降

ファイルから読み込みを行うには、ファイルクラスから入力ストリームを
取得し、ストリームから読み込みを行います。

SFXFile file;
SFXAnsiStringStreamReader reader;
SFXAnsiString temp;
SFXAnsiString string;   // 読み出した文字列を格納
SFXPath path("/data.txt");  // ファイル名

// ファイルオープン
if (file.OpenReadOnly(path) == SFERR_NO_ERROR) {
    // ファイルオープンに成功した
    
    // 入力ストリームの取得
    file.GetStreamReader(1024, &reader);
    while (!reader.Ends()) { // ファイルの終端まで
        if (reader.GetReadableSize() == 0) {
            reader.Fetch();
        }
        reader >> temp; // ファイルからデータを読み出す
        string += temp;
    }
    file.Close();
}

バージョン 3.0

ファイルから読み込みを行うには、ファイルストリームクラス SFUFileStream
使用します。

SFUFileStream fstream;
SFXAnsiString string;   // 読み出した文字列を格納
SFXAnsiString filename("/data.txt");

// ファイルオープン
if (fstream.Open(filename, _OFM_READ) == SFERR_NO_ERROR) {
    // ファイルオープンに成功した
    fstream >> string; // ファイルから全データを読み出す
    fstream.Close();
}

参照 SFXFile::OpenReadOnly | SFXFile::GetStreamReader |
SFXStreamReader::GetReadableSize | SFXStreamReader::Fetch

      

ファイルに書き込みを行う

バージョン 4.0 以降

ファイルから書き込みを行うには、ファイルクラスから出力ストリームを
取得し、ストリームに書き込みを行います。

SFXFile file;
SFXAnsiStringStreamWriter writer;
SFXAnsiString string("abcdefg"); // 書き込む文字列
SFXPath path("/data.txt"); // ファイル名

// ファイルオープン
if (file.OpenReadWrite(path) == SFERR_NO_ERROR) {
    // ファイルオープンに成功した
    
    // 出力ストリームの取得
    file.GetStreamWriter(string.GetLength(), &writer);
    writer << string;
    writer.Flush();
    file.Close();
}

バージョン 3.0

ファイルに書き込みを行うには、ファイルストリームクラス SFUFileStream
使用します。

SFUFileStream fstream;
SFXAnsiString string("abcdefg");      // 書き込む文字列
SFXAnsiString filename("/data.txt");     // ファイル名

//ファイル新規作成
if (fstream.Open(filename, _OFM_CREATE) == SFERR_NO_ERROR) {
    // 新規作成に成功したなら
    fstream << string;                 // ファイルに書き込み
    fstream.Close();
}

参照 SFXFile::OpenReadWrite | SFXFile::GetStreamWriter |
SFXStreamWirter::Flush

      

ディレクトリを作成する

バージョン 4.0 以降

ディレクトリを作成するには、SFXDirectory::Create 関数を使用します。

// ディレクトリの作成
if (SFXDirectory::Create(SFXPath("/data/dir/") == SFERR_NO_ERROR) {
    // 成功した場合
}

バージョン 3.0

ディレクトリを作成するには、SFBFileMgr::MkDir 関数を使用します。

SFBFileMgrSmp fileMgr = SFBFileMgr::NewInstance();

// ディレクトリの作成
if (fileMgr->MkDir("/data/dir/") == SFERR_NO_ERROR) {
    // 成功した場合
}

参照 SFXDirectory::Create | SFBFileMgr::MkDir | SFBFileMgr::NewInstance

      

ファイル・ディレクトリの存在を調べる

バージョン 4.0 以降

ファイル・ディレクトリの存在を調べるには、SFXFile::Exists 関数を使用します。

Bool b;

SFXFile::Exists(SFXPath("/data.txt"), &b);
if (b) {
    // 指定されたファイル・ディレクトリが存在する場合

}

バージョン 3.0

ファイル・ディレクトリの存在を調べるには、SFBFileMgr::Test 関数を使用します。

SFBFileMgrSmp fileMgr = SFBFileMgr::NewInstance();

if (fileMgr->Test("/data.txt") == SFERR_NO_ERROR ) {
    // 指定されたファイル・ディレクトリが存在する場合

}

参照 SFXFile::Exists | SFBFileMgr::Test | SFBFileMgr::NewInstance