FileFlush関数の働き・役割
FileFlush関数は、指定されたファイルハンドルを持つファイルのバッファ(データを一時的に保存する領域)に残っている全てのデータを、強制的にディスクに書き込むための関数です。
プログラムがファイルにデータを書き込む際、すぐにそのデータがディスク(HDDやSSDなどの長期保存用記憶装置)に保存されるわけではありません。多くの場合、データは一時的にバッファというメモリ上に保管され、その後まとめてディスクに書き込まれます。しかし、プログラムが予期せず終了したり、ファイルを閉じる前にエラーが発生したりすると、バッファ内のデータが失われる可能性があります。
FileFlush関数を使うと、バッファに残っているデータを即座にディスクに保存し、データの一貫性を確保できます。例えば、大量のデータをファイルに書き込む際に、定期的にディスクにデータを保存して途中でデータが失われないようにすることができます。
FileFlush関数の引数について
void FileFlush(
int file_handle // ファイルハンドル
);
FileFlush関数は1つの引数を取ります。
file_handle
- FileOpen関数で開かれたファイルの識別子(ハンドル)を指定します。
- このファイルハンドルは、ファイル操作を行うために必要なファイルへのアクセス権を表しています。FileOpen関数が正常に実行されると、ファイルハンドルが返されます。
- ファイルハンドルは、FileFlush関数を使用してバッファにあるデータをディスクに書き込む対象のファイルを指定するために必要です。
例えば、FileOpen関数によってファイルを開き、そのファイルハンドルがfile_handle変数に格納されます。その後、FileFlush関数を呼び出す際にfile_handleを指定することで、データをディスクに保存します。
ファイルハンドルが無効な場合、FileFlush関数は実行されません。そのため、FileOpen関数の処理が成功したことを確認する必要があります。
FileFlush関数の戻り値について
FileFlush関数には戻り値はありません。この関数はvoid型であり、データをディスクに書き込むことが目的のため、何も返しません。
ただし、ファイルハンドルが無効である場合や、書き込み処理中にエラーが発生した場合、データが正しく書き込まれない可能性があるため、FileFlush関数の前にFileOpen関数や他のファイル操作が正常に行われていることを確認することが重要です。
関数自体はデータをディスクに即座に保存する役割を果たしますが、処理が成功したかどうかのフィードバックは直接得られないため、事前にエラーチェックを行うことが推奨されます。
FileFlush関数を使ったサンプルコード
//--- スクリプトの起動時に入力パラメータのウィンドウを表示する設定
#property script_show_inputs
//--- 書き込みするファイル名を設定(入力パラメータとして扱う)
input string InpFileName="example.csv"; // 保存するファイル名
//--- スクリプトのメイン関数(スクリプトが実行されるとOnStartが呼び出される)
void OnStart()
{
//--- エラーコードをリセットして、直前のエラー情報をクリアする
ResetLastError();
//--- ファイルを開く(読み書きとCSV形式でファイルを扱う)
int file_handle = FileOpen(InpFileName, FILE_READ | FILE_WRITE | FILE_CSV);
//--- ファイルが正常に開けたかどうかをチェック
if (file_handle != INVALID_HANDLE) // ファイルが正常に開けた場合
{
//--- 1000回ループして、ファイルにデータを書き込む処理を行う
for (int i = 0; i < 1000; i++)
{
//--- 現在の時刻とシンボル(通貨ペアなど)のBidとAsk価格を書き込む
FileWrite(file_handle, TimeCurrent(), SymbolInfoDouble(Symbol(), SYMBOL_BID), SymbolInfoDouble(Symbol(), SYMBOL_ASK));
//--- 128回書き込みごとにバッファのデータをディスクに書き込む
//--- (i & 127) == 127 という条件は、iが128の倍数の時にtrueになる
if ((i & 127) == 127)
{
//--- FileFlushを呼び出し、バッファ内のデータをディスクに書き込む
FileFlush(file_handle);
//--- データが書き込まれたことを確認するためにエキスパートログに出力する
PrintFormat("i = %d, データがディスクに保存されました", i);
}
//--- プログラムが急に負荷をかけないように、0.01秒(10ミリ秒)休止する
Sleep(10);
}
//--- すべての書き込みが完了したら、ファイルを閉じる
FileClose(file_handle);
}
else // ファイルが開けなかった場合
{
//--- ファイルを開く際にエラーが発生したことをエキスパートログに表示する
PrintFormat("ファイルを開けませんでした。エラーコード = %d", GetLastError());
}
}
このサンプルコードは、指定したファイルに対して現在のサーバー時刻やシンボルのBid・Ask価格を1000回書き込み、128回ごとにバッファ内のデータをディスクに強制的に保存するものです。さらに、書き込みの進行状況をエキスパートログに出力し、最後にファイルを閉じて処理を終了します。
サンプルコードの解説
script_show_inputsプロパティは、スクリプトを実行する際に入力パラメータのウィンドウを表示させるための設定です。これにより、スクリプトを実行する前にユーザーが入力するパラメータを変更できるようになります。
input型のInpFileName変数は、ユーザーが変更できるパラメータを設定するために使われます。ここでは、書き込むファイルの名前を入力パラメータとして指定しています。InpFileNameは”example.csv”という初期値を持ちます。プログラムが動作する際、このファイルにデータが書き込まれます。
OnStart関数は、スクリプトが実行されたときに最初に呼び出される関数です。MQL5では、スクリプトが開始された際に必ずこの関数が自動的に実行され、プログラムのメインロジックがここに記述されます。今回のサンプルコードでも、ファイルのオープン、データの書き込み、ファイルのクローズなどの一連の処理がOnStart関数内にまとめられています。
ResetLastError関数は、前回のエラー情報をリセットします。これにより、次にエラーが発生した場合に、正しいエラーコードを取得できるようにします。
FileOpen関数は、ファイルを開くための関数です。この関数を使用することで、指定されたファイル名を、読み書き可能な状態かつCSV形式で開きます。ここで使用されているFILE_READ、FILE_WRITE、FILE_CSVの各識別子にはそれぞれ役割があります。
- FILE_READは、ファイルを読み込み専用で開くための識別子です。ファイルの内容をプログラム内で読み取ることができます。
- FILE_WRITEは、ファイルにデータを書き込むための識別子です。この識別子が指定されている場合、ファイルに対してデータの書き込みが可能になります。
- FILE_CSVは、ファイルをCSV(カンマ区切りのテキスト形式)として扱うための識別子です。この識別子を使うと、ファイル内のデータが自動的にカンマで区切られた形式で処理されます。
また、これらの識別子の間にあるパイプ記号はビット演算子で、複数のフラグを組み合わせるために使われます。この場合、FILE_READ、FILE_WRITE、FILE_CSVという構文は、ファイルを「読み込み」「書き込み」「CSV形式」という3つのモードで同時に開くことを意味します。
if文は、条件式が真である場合にブロック内の処理を実行します。ここでは、file_handleが有効な値かどうかを確認し、無効でなければファイル操作を進めます。else文はif文の条件が偽の場合に実行されます。つまり、ファイルが開けなかった場合の処理が記述されています。
for文は、指定した回数だけ繰り返し処理を実行するループ構文です。ここでは、iの値が0から999になるまでループを回し、1000回データを書き込む処理を行っています。
FileWrite関数は、ファイルにデータを書き込むための関数です。FileWrite関数には、書き込み対象となるファイルハンドルと、書き込むデータを引数として指定します。サンプルコードでは、以下の3つのデータがFileWrite関数に渡され、CSV形式でファイルに保存されます。
- TimeCurrent関数は、サーバーの現在時刻を取得するための関数です。この関数の戻り値は、dateTime型(日時情報を表す型)で、現在のサーバー時刻を返します。これにより、データが書き込まれたタイミングの時刻を記録することができます。
- SymbolInfoDouble関数(SYMBOL_BID)
- SymbolInfoDouble関数は、指定したシンボル(通貨ペアや銘柄)の情報を取得するための関数です。ここでは、SYMBOL_BIDというパラメータを渡すことで、シンボルのBid価格(買い価格)を取得しています。この価格は、データの一部としてファイルに書き込まれます。
- SymbolInfoDouble関数(SYMBOL_ASK)
- 同様に、SymbolInfoDouble関数にSYMBOL_ASKというパラメータを渡すことで、シンボルのAsk価格(売り価格)を取得しています。このデータもBid価格と一緒に書き込まれます。
これらの関数を使用することで、FileWrite関数に対して現在のサーバー時刻、シンボルのBid価格とAsk価格を引数として渡し、それらをファイルに書き込むことができます。結果として、ファイルには時刻と価格情報が逐次的に保存されていきます。
「(i & 127) == 127という条件式」はビット演算によって、iが128の倍数の時に真になります。128回ごとにFileFlush関数を呼び出し、バッファ内のデータをディスクに書き込むタイミングを決めています。
FileFlush関数は、バッファに蓄えられているデータを即座にディスクに書き込む関数です。通常、データは一時的にメモリ上に保存されますが、FileFlush関数を使うことで途中でディスクにデータを反映させることができます。これにより、データが失われるリスクを減らします。
PrintFormat関数は、指定された書式に従って文字列を作成し、その文字列をエキスパートログ(プログラムの実行状況を表示するウィンドウ)に出力します。ここでは、ループの進行状況をエキスパートログに表示して、データが保存されたことを確認しています。※ミリ秒とは1/1000秒を意味します。
Sleep関数は、指定した時間(ここでは10ミリ秒)の間、プログラムの実行を一時的に停止します。これにより、急激な負荷がかからないようにしながら処理を続けます。
FileClose関数は、最後にファイル操作が終わったらファイルを閉じます。FileClose関数を呼び出すことで、ファイルに対するすべての操作を終了し、システムリソースを解放します。