土木測量プログラムの開発 (ファイル操作)

2017/03/10


ファイルへの変数の書き出しと呼び出し。

アドインプログラムは電卓のメニューから呼び出された際に初期動作を行うようで変数などがリセットされます。 誤って MENU キーを押すことはよくあるので必要な変数をファイルに保存し、呼び出すようにします。

ファイルはメインメモリまたはストレージメモリに作成することができます。 SDカードにもできますが、SDカード付モデルを持っていないので動作の検証ができ無いため解説はしません。 ただ、ストレージメモリとの違いは FONTCHARACTER の書き方だけで、専用命令などはありません。

以下は新規プロジェクトの状態です。

#include "fxlib.h"

//****************************************************************************
int AddIn_main(int isAppli, unsigned short OptionNum) {
    unsigned int key;

    Bdisp_AllClr_DDVRAM();

    locate(1,4);
    Print((unsigned char*)"This application is");
    locate(1,5);
    Print((unsigned char*)" sample Add-In.");

    while(1) {
        GetKey(&key);
    }

    return 1;
}

ファイル操作を関数として登録し呼び出します。 変更部分は別に関数を作成しメイン部分から関数を呼び出します。 これにより関数の変更のみの記述で済みます。

このサンプルではファイル名を "\\fls0\testfile.dat" とし、プログラムの先頭で定義しています。

以下は関数内での処理となります。

初めにファイルをオープンしますが、ファイルが存在しない場合は新規にファイルを作成しオープンします。

ファイルの先頭に int型 の数値を書き込んだ後、変数 val に別の数値を代入し表示します。

その後、ファイルから数値を呼び出し、val に書き込んだ後、変数 val の内容を表示します。

最後にファイルをクローズして終了です。

#include "fxlib.h"
#include "stdio.h"

// ファイル名を定義
static const FONTCHARACTER filename[] = {'\\','\\','f','l', 's', '0','\\','t','e','s','t','f','i','l','e','.','d','a','t',0};

//****************************************************************************
int AddIn_main(int isAppli, unsigned short OptionNum) {
    unsigned int key;

    Bdisp_AllClr_DDVRAM();

    file_test();

    while(1) {
        GetKey(&key);
    }

    return 1;
}

//*** Function ***
int file_test(void) {

    int fileHandle;
    int fileAddress;
    unsigned char text1[20];
    int val, tmp, size;

    fileHandle = Bfile_OpenFile(filename, _OPENMODE_READWRITE);  // ファイルのオープン
    if (fileHandle < 0) {
        Bfile_CreateFile(filename, 100);  // オープンに失敗した場合、新規にファイルを作成。
        fileHandle = Bfile_OpenFile(filename, _OPENMODE_READWRITE);
    }

    val = 12345;

    tmp = Bfile_SeekFile (fileHandle, 0);  // 書き込みポインタに 0 番を指定
    fileAddress = Bfile_WriteFile(fileHandle, &val, 4); ファイルに変数 val の値を書き込み。 val は int型なので 4バイト使用。

    val = 6789;

    sprintf(text1, "%d", val);
    locate(1,4);
    Print(text1);

    tmp = Bfile_ReadFile (fileHandle, &val, 4, 0);  //ファイルの 0番から 4バイト読み込み、変数 val に保存。
    sprintf(text1, "%d", val);  // 数値を文字に変換

    locate(1,5);
    Print(text1);

    tmp = Bfile_CloseFile(fileHandle);  // ファイルをクローズ

    return 1;
}

ストレージメモリでなくメインメモリにファイルを作成して上記と同じ動作を挿せてみます。

メインメモリにファイルを作成する場合、 FONTCHARACTER を使用しない代りにファイル名を宣言します。

ストレージメモリの命令との違いは、ファイルのオープンと新規作成の命令とディレクトリに対する命令が無いくらいです。 以下のプログラムは上記の Bfile_OpenFile命令と Brile_CreateFile命令の部分を書き換えています。

#include "fxlib.h"
#include <stdio.h>

static unsigned char filename[] = "testfile";  // ファイル名を指定。ディレクトリは不可
//*** Function ***
int file_test(void) {

    int fileHandle;
    int fileAddress;
    unsigned char text1[20];
    int val, tmp, size;

    fileHandle = Bfile_OpenMainMemory(filename);  // ファイルのオープン命令が異なる
    if (fileHandle < 0) {
        Bfile_CreateMainMemory(filename);  // 新規作成コマンドが異なる
        fileHandle = Bfile_OpenMainMemory(filename);
    }

    val = 12345;

    tmp = Bfile_SeekFile (fileHandle, 1);
    fileAddress = Bfile_WriteFile(fileHandle, &val, 4);

    val = 6789;

    sprintf(text1, "%d", val);
    locate(1,4);
    Print(text1);

    tmp = Bfile_ReadFile (fileHandle, &val, 4, 1);
    sprintf(text1, "%d", val);

    locate(1,5);
    Print(text1);

    tmp = Bfile_CloseFile(fileHandle);

    return 1;
}

ファイルのアドレス 0x0 にデータを保存出来ることは確認できたのですが、正常に呼び出しが出来ませんでした。 エミュレータだけのエラーかもしれませんが、データをロストしたくないので 0x1 から書き込みするようにします。


エラー時の動作。

ファイルが存在しない時の処理は上記で確認できましたが、いくつかエラー時の動作を検証してみます。

ファイルサイズ以上の書き込み、読み込みを行った時の動作

ファイルを新規作成時にファイルサイズを指定しますが、それよりも多くのデータが書き込まれたときにどうなるかを確認してみます。

以下のプログラムでは、ファイルの新規作成時に 10 バイトを指定後、20 バイトのデータを書き込んでみます。 プログラムを実行する前にメモリマネージャを使用しストレージメモリに "text" が無いことを確認し、あれば削除してください。

/*****************************************************************/
#include <stdio.h>
#include "fxlib.h"
// ファイル名 "\fls0\test"
static const FONTCHARACTER filename[] = {'\\','\\','f','l', 's', '0','\\','t','e','s','t',0};

//****************************************************************************
int AddIn_main(int isAppli, unsigned short OptionNum) {
    unsigned int key;
    int fileHandle;
    int fileAddress;
    int tmp;
    int i;
    char c;
    char txt[] = "ABCDEFGHIJKLMNOPQRST";

    Bfile_CreateFile(filename, 10);  // 10バイトのファイルを新規作成
    fileHandle = Bfile_OpenFile(filename, _OPENMODE_READWRITE);  // ファイルをオープン

    tmp = Bfile_SeekFile (fileHandle, 0);  // ファイルポインタを指定
    fileAddress = Bfile_WriteFile(fileHandle, &txt, 20);  // 20バイト書き込み

    for(i=0; i<20; i++) { //文字列 txt を初期化
        txt[i] = 0;
    }

    for(i=0; i<20; i++) {  // 20バイト読み込み
        tmp = Bfile_ReadFile (fileHandle, &txt, 20, 0);
    }

    tmp = Bfile_CloseFile(fileHandle);  // ファイルをクローズ

    locate(1, 1);
    Print((unsigned char*)txt);  // 読込結果を表示

    while(1) GetKey(&key);
    return 1;
}

上のプログラムを実行してもファイルサイズは 10バイトのままで、自動でファイルが大きくなるということはありません。 10バイトまでは正常に書き込まれているようです。

読み込み時にサイズ以上のポインタ指定を行っても何も読み込まれません。

ただし、ファイルサイズ以上のポインタを指定して書き込もうとすると、エミュレータ上ではシステムのエラーが出てしまいます。 実機でも同じような動作をすると思います。

書き込み、読み込み、位置指定のいずれの命令にも戻り値があるので、戻り値のチェックをすることで処理が可能かどうか確認することができます。


テキスト ファイルの読み書き。

PC で作ったデータをプログラムに読み込むため、テキストファイルの取り扱いを色々と実験してみましたが、よくわからない所でエラーが出てしまい、正常な書き込みができませんでした。

なんとか実行できるようにしたいのですが、この部分は後回しにします。