FileReadArray関数の働き・役割
FileReadArray関数は、バイナリ形式(BIN)のファイルからデータを読み込み、そのデータを配列に格納するために使用されます。この関数は、任意の型(string型を除く)で構成された動的配列や構造体の配列に対応しており、ファイルの内容を直接配列に読み込むことができます。特に、価格データや履歴などの複数の要素を持つデータセットを効率的に処理する際に便利です。
また、FileReadArray関数は、指定されたファイルハンドルを使用してファイルを読み込み、必要に応じて配列のサイズを自動的に拡張するため、配列サイズの事前定義が不要です。例えば、取引履歴や複数の価格データを記録したファイルから、そのデータを配列に読み込むケースに適しています。
FileReadArray関数の引数について
FileReadArray関数の引数構成は以下の通りです。
uint FileReadArray(
int file_handle, // ファイルハンドル
void& array[], // 記録するための配列
int start=0, // 配列の書き初めの位置
int count=WHOLE_ARRAY // 読みのカウント
);
第1引数:file_handle
ファイルハンドルは、ファイル操作を行う際に必要な識別子です。この識別子は、事前にFileOpen関数によって生成されます。FileOpen関数が正常にファイルを開けた場合、その戻り値として有効なハンドルが返されます。このハンドルを使って、FileReadArray関数が正しくデータを読み取ることができます。もし無効なハンドル(INVALID_HANDLE)が渡された場合、読み込みは行われません。
第2引数:array[]
第2引数には特定の配列を記述します。
この配列は、ファイルから読み込んだデータを格納するための場所です。この配列はstring型以外の任意の型で構成される動的配列または構造体の配列を指定します。たとえば、価格データやカスタムデータ構造体を読み込む場合、あらかじめ配列や構造体の定義をしておく必要があります。FileReadArray関数は、この配列にファイルから読み取ったデータを順次格納します。
第3引数:start=0
第3引数は、読み取ったデータを格納する配列内の開始位置を指定します。初期値は0であり、配列の先頭から書き込みが始まります。この値を変更することで、特定の位置からデータを上書きして読み込むことが可能です。
第4引数:count=WHOLE_ARRAY
第4引数は、読み込む要素数を指定します。デフォルト値はWHOLE_ARRAYであり、指定がない場合は配列全体に対してデータを読み込みます。特定の要素数だけ読み込みたい場合には、その数を明示的に指定することが可能です。
FileReadArray関数の戻り値について
FileReadArray関数の戻り値は、実際にファイルから読み込まれた要素の数を返します。これにより、配列にどれだけのデータが格納されたかを確認することができます。
FileReadArray関数を使う際の注意点
FileReadArray関数は、文字列の配列を読み込む場合、TXT形式のファイルからしか読み取れません。また、読み込むデータの型が配列の型と一致しない場合、正しくデータが格納されないことがあります。
さらに、ファイルが破損している場合や無効なファイルハンドルが指定された場合、読み込みが失敗する可能性があるため、FileOpen関数でファイルハンドルの有効性を確認することが重要です。
FileReadArray関数を使ったサンプルコード
//--- スクリプトの起動時に入力パラメータのウィンドウを表示する
#property script_show_inputs
//--- 入力パラメータを定義する(ファイル名とディレクトリ名をユーザが指定可能)
input string InpFileName="data.bin"; // 読み込むバイナリファイルの名前
input string InpDirectoryName="SomeFolder"; // 読み込むファイルが保存されているフォルダ名
//+------------------------------------------------------------------+
//| 価格データを格納するための構造体 |
//+------------------------------------------------------------------+
struct prices
{
datetime date; // 日付データを保持する(取引日)
double bid; // 売値(Bid価格)を保持する
double ask; // 買値(Ask価格)を保持する
};
//+------------------------------------------------------------------+
//| スクリプトプログラムを開始する関数 |
//+------------------------------------------------------------------+
void OnStart()
{
//--- 構造体配列を定義する(ファイルからデータを読み込むために使用する)
prices arr[];
//--- ファイルのパスを設定する(ディレクトリ名とファイル名を結合)
string path=InpDirectoryName+"//"+InpFileName;
//--- エラー情報をリセットする(エラーが発生した場合に備えて初期化)
ResetLastError();
//--- バイナリファイルを読み取り専用で開く
int file_handle=FileOpen(path,FILE_READ|FILE_BIN);
//--- ファイルが正常に開けたかどうか確認する
if(file_handle!=INVALID_HANDLE)
{
//--- ファイルから全データを配列に読み込む
FileReadArray(file_handle,arr);
//--- 読み込んだ配列の要素数(データのサイズ)を取得する
int size=ArraySize(arr);
//--- 読み込んだデータを配列から一つずつ取り出して表示する
for(int i=0;i<size;i++)
Print("Date = ",arr[i].date," Bid = ",arr[i].bid," Ask = ",arr[i].ask);
//--- 読み込んだデータの総数を表示する
Print("Total data = ",size);
//--- ファイルを閉じる(ファイル操作が終わったら必ず閉じる)
FileClose(file_handle);
}
else
//--- ファイルが開けなかった場合のエラーメッセージを表示する
Print("File open failed, error ",GetLastError());
}
サンプルコード解説1
//--- スクリプトの起動時に入力パラメータのウィンドウを表示する
#property script_show_inputs
//--- 入力パラメータを定義する(ファイル名とディレクトリ名をユーザが指定可能)
input string InpFileName="data.bin"; // 読み込むバイナリファイルの名前
input string InpDirectoryName="SomeFolder"; // 読み込むファイルが保存されているフォルダ名
//+------------------------------------------------------------------+
//| 価格データを格納するための構造体 |
//+------------------------------------------------------------------+
struct prices
{
datetime date; // 日付データを保持する(取引日)
double bid; // 売値(Bid価格)を保持する
double ask; // 買値(Ask価格)を保持する
};
このセクションでは、スクリプトの初期設定に関するコードの動作を詳しく解説します。
#property script_show_inputs
この行は、スクリプトを実行する際に入力パラメータのウィンドウを表示するためのものです。入力パラメータウィンドウを通じて、ユーザーは実行時に必要な設定を行うことができます。この設定により、ファイル名やディレクトリ名をユーザーが指定できるようになります。
入力パラメータの定義
次に、スクリプトで使用される入力パラメータを定義しています。ここで定義されているパラメータは、ファイル名とディレクトリ名の2つです。
InpFileName は、読み込むファイルの名前を指定します。ここでは、デフォルトで “data.bin” という名前のバイナリファイルが指定されています。ユーザーはこのパラメータを変更して、異なるファイルを指定することも可能です。
InpDirectoryName は、ファイルが保存されているディレクトリ名を指定します。このパラメータもユーザーが変更可能で、デフォルトでは “SomeFolder” というフォルダが指定されています。
この2つのパラメータは、ファイルパスを動的に構成するために利用されます。
構造体の定義
次に、価格データを格納するための構造体が定義されています。
dateTime date は、取引が行われた日付を保持するためのフィールドです。dateTime型は、日時データを扱うための型です。
double bid は、売値(Bid価格)を保持します。Bid価格とは、買い手が購入する際に支払う価格のことです。
double ask は、買値(Ask価格)を保持します。Ask価格は、売り手が販売する際に提示する価格です。
この構造体は、ファイルから読み込んだ価格データを整理して格納するために使用されます。複数の価格データを配列として管理できるようになっています。
サンプルコード解説2
//+------------------------------------------------------------------+
//| スクリプトプログラムを開始する関数 |
//+------------------------------------------------------------------+
void OnStart()
{
//--- 構造体配列を定義する(ファイルからデータを読み込むために使用する)
prices arr[];
//--- ファイルのパスを設定する(ディレクトリ名とファイル名を結合)
string path=InpDirectoryName+"//"+InpFileName;
//--- エラー情報をリセットする(エラーが発生した場合に備えて初期化)
ResetLastError();
//--- バイナリファイルを読み取り専用で開く
int file_handle=FileOpen(path,FILE_READ|FILE_BIN);
このセクションでは、スクリプトのメイン処理であるファイルの読み込みに関するコードを解説します。
OnStart関数
OnStart関数は、スクリプトが実行された際に最初に呼び出される関数です。この関数内で、ファイルからデータを読み込むための処理を実行します。
構造体配列の定義
まず、ファイルから読み込んだデータを格納するために、構造体で定義された配列を宣言しています。
prices arr[] は、事前に定義されたprices構造体の配列です。これにより、ファイルから読み込んだ複数の価格データを一時的に保持することができます。データが増えるたびに動的に配列のサイズが拡張されます。
ファイルのパスを設定
次に、ファイルのパスを設定します。
path変数には、ユーザーが入力したディレクトリ名とファイル名を結合した文字列が格納されます。これにより、正確なファイルパスを指定することができ、スクリプトはこのパスを使用してファイルを開きます。ここで、InpDirectoryNameとInpFileNameの入力値を組み合わせて、読み込むファイルを指定しています。
エラー情報をリセット
ResetLastError関数は、ファイルを開く前にエラー情報をリセットして、以前の操作で発生したエラーが残っていないかを確認します。これにより、次に発生するエラーが確実に検知され、正確に処理できるようになります。
バイナリファイルのオープン
FileOpen関数を使用して、指定されたファイルパスのバイナリファイルを読み取り専用で開きます。
file_handle変数には、ファイルが正常に開かれた場合にファイルハンドルが格納されます。FileOpen関数が無効なファイルハンドル(INVALID_HANDLE)を返した場合は、エラーが発生していることを意味します。このファイルハンドルは、後の処理でファイル操作を行うために使用されます。
FILE_READはファイル操作のフラグで、ファイルを「読み取り専用」で開くことを指定します。
| はビット単位の論理演算(ビット演算)における「ビット単位の論理和」を表す演算子です。ここでは複数のフラグを組み合わせて指定するために使用されています。例えば、FILE_READとFILE_BINのフラグを組み合わせることで、ファイルを読み取り専用かつバイナリ形式で開くことができます。この演算子を使用することで、複数の設定を一つにまとめて指定できるようになります。
FILE_BINもファイル操作の際に使用されるフラグの一つです。このフラグは、ファイルをバイナリ形式で開くことを指定します。バイナリ形式とは、ファイル内のデータをそのままバイト単位で扱う形式のことです。テキスト形式ではなく、数値データや構造体データをそのまま保存・読み込みできるため、効率的にデータ操作が可能になります。
FileOpen(path, FILE_READ | FILE_BIN)
の記述を端的に日本語訳すれば、「ファイルを読み取り専用かつバイナリ形式で開く」ということになります。
サンプルコード解説3
//--- ファイルが正常に開けたかどうか確認する
if(file_handle!=INVALID_HANDLE)
{
//--- ファイルから全データを配列に読み込む
FileReadArray(file_handle,arr);
//--- 読み込んだ配列の要素数(データのサイズ)を取得する
int size=ArraySize(arr);
//--- 読み込んだデータを配列から一つずつ取り出して表示する
for(int i=0;i<size;i++)
Print("Date = ",arr[i].date," Bid = ",arr[i].bid," Ask = ",arr[i].ask);
//--- 読み込んだデータの総数を表示する
Print("Total data = ",size);
//--- ファイルを閉じる(ファイル操作が終わったら必ず閉じる)
FileClose(file_handle);
}
else
//--- ファイルが開けなかった場合のエラーメッセージを表示する
Print("File open failed, error ",GetLastError());
}
このセクションでは、ファイルからデータを読み込み、処理を行う部分について解説します。
ファイルが正常に開けたかの確認
まず、ファイルが正しく開けたかを確認しています。
この条件文は、ファイルが正常に開かれたかをチェックしています。FileOpen関数が成功した場合、ファイルハンドル(識別子)が返されます。失敗した場合は無効なハンドルが返されるため、ファイルが開けなかった場合はこの条件によりエラーハンドリングを行います。
ファイルからデータを配列に読み込む
この行で、FileReadArray関数を使用してファイルからデータを配列に読み込んでいます。ファイルハンドルを指定し、配列にデータを格納します。この配列には、事前に定義された構造体に基づいて、複数のデータ(価格情報)が格納されます。
読み込んだ配列の要素数を取得
FileReadArray関数を使用して読み込んだ配列の要素数、つまり配列内に格納されたデータの数をArraySize関数で取得しています。これにより、どれだけのデータが読み込まれたかを知ることができます。
配列のデータを表示する
このループでは、配列内の各要素を順番に取り出して表示しています。具体的には、日付、売値、買値を一つずつ出力しています。
この行で、構造体に格納されているデータを表示しています。それぞれの取引の日時と価格情報が、コンソールに出力されます。
総データ数の表示
この行で、読み込んだデータの総数を表示します。配列に格納された要素の数(データの件数)を確認できるようになっています。
ファイルのクローズ処理
ファイル操作が終了した後は、FileClose関数を使って必ずファイルを閉じます。これにより、ファイルハンドルのリソースが解放され、次回のファイル操作に問題が発生しないようになります。
ファイルが開けなかった場合のエラーメッセージ
ファイルが開けなかった場合、この行でエラーメッセージが表示されます。GetLastError関数を使用して、最後に発生したエラーコードを取得し、その詳細を出力します。