FileGetInteger関数の働き・役割
FileGetInteger関数は、ファイルの整数プロパティ(属性や情報)を取得するために使用されます。この関数には2つのバージョンがあり、ファイルハンドルでプロパティを取得する方法と、ファイル名でプロパティを取得する方法があります。
ファイルハンドルとは?
ファイルハンドルとは、ファイル操作を行う際に使用される一種の識別子です。ファイルを開くときに取得され、このハンドルを使用することで、特定のファイルに対して読み書きや属性取得などの操作を行うことができます。ファイルハンドルは、ファイルが開かれている間のみ有効であり、操作が完了したら必ず閉じる必要があります。
FileGetInteger関数の引数について
FileGetInteger関数は複数の書式を持つオーバーロード関数であり、ファイルハンドルでプロパティを取得する方法と、ファイル名でプロパティを取得する方法があります。
1. ファイルハンドルでプロパティを取得する場合
long FileGetInteger(
int file_handle, // ファイルハンドル
ENUM_FILE_PROPERTY_INTEGER property_id // プロパティ識別子
);
- file_handle
種類: 整数型
説明: FileOpen関数から戻されたファイル記述子(ファイルハンドル)です。このハンドルを使ってファイルのプロパティ(属性や情報)を取得します。 - property_id
種類: ENUM_FILE_PROPERTY_INTEGER
説明: 取得するファイルプロパティの識別子です。プロパティ識別子はENUM_FILE_PROPERTY_INTEGERR列挙のいずれかの値です。
2. ファイル名でプロパティを取得する場合
long FileGetInteger(
const string file_name, // ファイル名
ENUM_FILE_PROPERTY_INTEGER property_id, // プロパティ ID
bool common_folder=false // ファイルがローカルフォルダでみられる(false)
// または全てのクライアント端末でみられる(true)
);
- file_name
種類: 文字列
説明: プロパティを取得するファイルの名前です。 - property_id
種類: ENUM_FILE_PROPERTY_INTEGER
説明: 取得するファイルプロパティの識別子です。使用できるプロパティ識別子は、FILE_EXISTS、FILE_CREATE_DATE、FILE_MODIFY_DATE、FILE_ACCESS_DATE、およびFILE_SIZEです。 - common_folder
種類: ブール値(初期値はfalse)
説明: ファイルの位置を示すフラグです。falseの場合、ファイルは端末データフォルダに存在し、trueの場合、ファイルは全てのクライアント端末(ユーザーのコンピュータ)の共有フォルダに存在します。
FileGetInteger関数の戻り値について
FileGetInteger関数は、指定されたプロパティの値を返します。プロパティの取得に成功した場合、そのプロパティの整数値が返されます。取得に失敗した場合は-1を返します。
エラーが発生した場合、具体的なエラーコードはGetLastError関数を使用して取得できます。ファイル名でプロパティを取得する際にフォルダを指定された場合、この関数は正しい戻り値を返しつつも、エラー5018(ERR_MQL_FILE_IS_DIRECTORY)を発生させることがあります。
FileGetInteger関数を使う際の注意点
FileGetInteger関数を使用する際の注意点は以下の通りです:
- FileGetInteger関数は、呼び出されるたびにエラーコードを設定します。関数が正常に完了した場合、エラーコードは0(NULL)にリセットされますが、エラーが発生した場合は具体的なエラーコードが設定されます。このエラーコードは、GetLastError関数を使って確認できます。
- ファイル名でプロパティを取得する場合、フォルダを指定するとエラー5018(ERR_MQL_FILE_IS_DIRECTORY)が発生することがあります。このエラーは、指定されたファイルがディレクトリである場合に発生します。
FileGetInteger関数を使ったサンプルコード
以下に、FileGetInteger関数を使用したサンプルコードを示します。このコードは、指定されたファイルのプロパティを取得してエキスパートログに出力します。
//--- スクリプトの起動時に入力パラメータのウィンドウを表示する
#property script_show_inputs
//--- 入力パラメータ
input string InpFileName="data.csv"; // デフォルトのファイル名
input string InpDirectoryName="SomeFolder"; // デフォルトのディレクトリ名
//+------------------------------------------------------------------+
//| スクリプトプログラムを開始する関数 |
//+------------------------------------------------------------------+
void OnStart()
{
// ファイルパスを生成
string path = InpDirectoryName + "\\" + InpFileName;
long l = 0; // プロパティ値を格納する変数
//--- ファイルを開く
ResetLastError(); // エラーコードをリセット
int handle = FileOpen(path, FILE_READ | FILE_CSV); // ファイルを読み取りモードで開く
if(handle != INVALID_HANDLE) // ファイルが正常に開かれたかを確認
{
//--- ファイルの情報を全て出力する
Print(InpFileName, " file info:");
FileInfo(handle, FILE_EXISTS, l, "bool"); // ファイルが存在するかどうか
FileInfo(handle, FILE_CREATE_DATE, l, "date"); // ファイルの作成日
FileInfo(handle, FILE_MODIFY_DATE, l, "date"); // ファイルの最終更新日
FileInfo(handle, FILE_ACCESS_DATE, l, "date"); // ファイルの最終アクセス日
FileInfo(handle, FILE_SIZE, l, "other"); // ファイルのサイズ
FileInfo(handle, FILE_POSITION, l, "other"); // ファイル内の現在の位置
FileInfo(handle, FILE_END, l, "bool"); // ファイルの終わりかどうか
FileInfo(handle, FILE_IS_COMMON, l, "bool"); // ファイルが共有フォルダにあるかどうか
FileInfo(handle, FILE_IS_TEXT, l, "bool"); // ファイルがテキストファイルかどうか
FileInfo(handle, FILE_IS_BINARY, l, "bool"); // ファイルがバイナリファイルかどうか
FileInfo(handle, FILE_IS_CSV, l, "bool"); // ファイルがCSVファイルかどうか
FileInfo(handle, FILE_IS_ANSI, l, "bool"); // ファイルがANSIエンコードかどうか
FileInfo(handle, FILE_IS_READABLE, l, "bool"); // ファイルが読み取り可能かどうか
FileInfo(handle, FILE_IS_WRITABLE, l, "bool"); // ファイルが書き込み可能かどうか
//--- ファイルを閉じる
FileClose(handle); // ファイルハンドルを閉じる
}
else
// ファイルが開けなかった場合のエラーメッセージを出力
PrintFormat("%s file is not opened, ErrorCode = %d", InpFileName, GetLastError());
}
//+------------------------------------------------------------------+
//| ファイルプロパティ値を表示する関数 |
//+------------------------------------------------------------------+
void FileInfo(const int handle, const ENUM_FILE_PROPERTY_INTEGER id,
long l, const string type)
{
//--- プロパティ値を受け取る
ResetLastError(); // エラーコードをリセット
if((l = FileGetInteger(handle, id)) != -1) // プロパティ値の取得に成功したかどうか
{
//--- 値を受け取ったので、正しいフォーマットで表示する
if(!StringCompare(type, "bool"))
Print(EnumToString(id), " = ", l ? "true" : "false"); // 真偽値として出力
if(!StringCompare(type, "date"))
Print(EnumToString(id), " = ", (datetime)l); // 日付として出力
if(!StringCompare(type, "other"))
Print(EnumToString(id), " = ", l); // その他の形式として出力
}
else
// エラーが発生した場合のエラーメッセージを出力
Print("Error, Code = ", GetLastError());
}
若干複雑なので、小分けにして解説していきたいと思います。
解説1:グローバル領域の定義部分
//--- スクリプトの起動時に入力パラメータのウィンドウを表示する
#property script_show_inputs
//--- 入力パラメータ
input string InpFileName="data.csv"; // デフォルトのファイル名
input string InpDirectoryName="SomeFolder"; // デフォルトのディレクトリ名
#property script_show_inputs
#property script_show_inputs
は、スクリプトが起動する際に入力パラメータウィンドウを表示するためのディレクティブです。
ディレクティブとは、コンパイラ(プログラムを機械語に翻訳するソフトウェア)に対して特定の動作を指示するための命令です。
このディレクティブを使用することで、ユーザーがスクリプトを実行する前に入力パラメータを設定できるようになります。
input string InpFileName=”data.csv”;
input
string InpFileName="data.csv";
は、スクリプトが実行される際にユーザーが指定できる入力パラメータを定義しています。このパラメータはスクリプトの実行中に変更することはできませんが、実行前にユーザーが値を設定できます。
- input
このキーワードは、ユーザーがスクリプト実行時に設定できるパラメータを定義するために使用されます。 - string
パラメータのデータ型を示しています。この場合、文字列型のパラメータです。 - InpFileName
パラメータの名前です。スクリプト内でこの名前を使用して、ユーザーが指定した値にアクセスします。 - “data.csv”
パラメータの初期値です。この初期値は、デフォルトで使用されるファイル名を示しています。
input string InpDirectoryName=”SomeFolder”;
input
string InpDirectoryName="SomeFolder";
も同様に、ユーザーが指定できる入力パラメータを定義しています。
- input
ユーザーがスクリプト実行時に設定できるパラメータを定義します。 - string
パラメータのデータ型を示しています。こちらも文字列型です。 - InpDirectoryName
パラメータの名前です。スクリプト内でこの名前を使用して、ユーザーが指定した値にアクセスします。 - “SomeFolder”
パラメータの初期値です。この初期値は、デフォルトで使用されるディレクトリ名を示しています。
これらの設定により、スクリプト実行時にユーザーがファイル名やディレクトリ名を簡単に指定できるようになります。
解説2:OnStart関数の中1
void OnStart()
{
// ファイルパスを生成
string path = InpDirectoryName + "\\" + InpFileName;
long l = 0; // プロパティ値を格納する変数
//--- ファイルを開く
ResetLastError(); // エラーコードをリセット
int handle = FileOpen(path, FILE_READ | FILE_CSV); // ファイルを読み取りモードで開く
void OnStart()
void OnStart()は、スクリプトが開始される際に最初に実行される関数です。MQL5では、スクリプト、エキスパートアドバイザー、インジケータなどの各プログラムタイプごとに特定のエントリポイント関数が用意されています。スクリプトの場合、OnStart関数がそのエントリポイントとなります。この関数は戻り値を持たず、引数も取りません。スクリプトが実行されると、この関数内のコードが一度だけ実行されます。
ファイルパスを生成
string path = InpDirectoryName + "\\" + InpFileName;
- string path
新しい文字列型の変数pathを宣言しています。この変数はファイルのパスを格納します。 - InpDirectoryName + “\” + InpFileName
ディレクトリ名InpDirectoryNameとファイル名InpFileNameを連結して、完全なファイルパスを生成します。 - バックスラッシュが2つ続いている理由:
バックスラッシュ(\)はエスケープシーケンス(特定の機能を持つ文字列)を示すために使用されます。例えば、\nは改行を示します。しかし、単純に文字としてバックスラッシュを使用したい場合、エスケープシーケンスとして解釈されないようにするためには、バックスラッシュを2つ続けて記述する必要があります。これにより、文字列内で単一のバックスラッシュが表示されます。
プロパティ値を格納する変数
long l = 0;
ファイルを開く
ResetLastError(); // エラーコードをリセット
- ResetLastError()
最後に発生したエラーコードをリセットします。ResetLastError関数を呼び出すことで、以前のエラーコードがクリアされ、次に発生するエラーを正しく検出できるようになります。
int handle = FileOpen(path, FILE_READ | FILE_CSV); // ファイルを読み取りモードで開く
- int handle
新しい整数型の変数handleを宣言します。この変数はファイルハンドルを格納します。 - FileOpen(path, FILE_READ | FILE_CSV)
FileOpen関数を使用して、指定されたパスのファイルを開きます。ここでは、読み取りモード(FILE_READ)とCSVモード(FILE_CSV)でファイルを開きます。戻り値はファイルハンドルです。ファイルハンドルは、ファイル操作を行うための識別子であり、このハンドルを使ってファイルの読み取りやプロパティの取得などを行います。
セパレータの | の文法的役割
- FILE_READ | FILE_CSV
セパレータの | はビット単位の論理和演算子を示します。これは複数のフラグを組み合わせるために使用されます。ここでは、FILE_READとFILE_CSVの両方のモードでファイルを開くために使用されています。ビット単位の論理和演算により、各フラグのビットが設定され、複数のオプションを同時に指定することができます。
解説3:OnStart関数の中2
if(handle != INVALID_HANDLE) // ファイルが正常に開かれたかを確認
{
//--- ファイルの情報を全て出力する
Print(InpFileName, " file info:");
FileInfo(handle, FILE_EXISTS, l, "bool"); // ファイルが存在するかどうか
FileInfo(handle, FILE_CREATE_DATE, l, "date"); // ファイルの作成日
FileInfo(handle, FILE_MODIFY_DATE, l, "date"); // ファイルの最終更新日
FileInfo(handle, FILE_ACCESS_DATE, l, "date"); // ファイルの最終アクセス日
FileInfo(handle, FILE_SIZE, l, "other"); // ファイルのサイズ
FileInfo(handle, FILE_POSITION, l, "other"); // ファイル内の現在の位置
FileInfo(handle, FILE_END, l, "bool"); // ファイルの終わりかどうか
FileInfo(handle, FILE_IS_COMMON, l, "bool"); // ファイルが共有フォルダにあるかどうか
FileInfo(handle, FILE_IS_TEXT, l, "bool"); // ファイルがテキストファイルかどうか
FileInfo(handle, FILE_IS_BINARY, l, "bool"); // ファイルがバイナリファイルかどうか
FileInfo(handle, FILE_IS_CSV, l, "bool"); // ファイルがCSVファイルかどうか
FileInfo(handle, FILE_IS_ANSI, l, "bool"); // ファイルがANSIエンコードかどうか
FileInfo(handle, FILE_IS_READABLE, l, "bool"); // ファイルが読み取り可能かどうか
FileInfo(handle, FILE_IS_WRITABLE, l, "bool"); // ファイルが書き込み可能かどうか
//--- ファイルを閉じる
FileClose(handle); // ファイルハンドルを閉じる
}
if(handle != INVALID_HANDLE)
- ファイルハンドルが有効かどうかを確認しています。FileOpen関数が無効なハンドルを返した場合(INVALID_HANDLE)、ファイルが正常に開かれていないことを示します。この条件を満たす場合にのみ、以下のコードブロックが実行されます。
Print(InpFileName, ” file info:”)
- 開いたファイルの情報を出力する準備をします。この行は、ファイル名と「file info:」というテキストをエキスパートログに出力します。
FileInfo(handle, FILE_EXISTS, l, “bool”)
- FileInfo関数を呼び出して、特定のファイルプロパティを取得します。この場合、ファイルが存在するかどうか(trueまたはfalse)を確認します。
※FileInfo関数はオリジナル関数です。定義に関してはOnStart関数の下で行っています。
FileInfo(handle, FILE_CREATE_DATE, l, "date"); // ファイルの作成日
FileInfo(handle, FILE_MODIFY_DATE, l, "date"); // ファイルの最終更新日
FileInfo(handle, FILE_ACCESS_DATE, l, "date"); // ファイルの最終アクセス日
- これらの呼び出しは、それぞれファイルの作成日、最終更新日、最終アクセス日を取得し、エキスパートログに出力します。
FileInfo(handle, FILE_SIZE, l, "other"); // ファイルのサイズ
FileInfo(handle, FILE_POSITION, l, "other"); // ファイル内の現在の位置
- ファイルのサイズと現在の読み取り位置を取得し、エキスパートログに出力します。
FileInfo(handle, FILE_END, l, "bool"); // ファイルの終わりかどうか
- ファイルの終わりに到達したかどうかを確認します。
FileInfo(handle, FILE_IS_COMMON, l, "bool"); // ファイルが共有フォルダにあるかどうか
FileInfo(handle, FILE_IS_TEXT, l, "bool"); // ファイルがテキストファイルかどうか
FileInfo(handle, FILE_IS_BINARY, l, "bool"); // ファイルがバイナリファイルかどうか
FileInfo(handle, FILE_IS_CSV, l, "bool"); // ファイルがCSVファイルかどうか
FileInfo(handle, FILE_IS_ANSI, l, "bool"); // ファイルがANSIエンコードかどうか
FileInfo(handle, FILE_IS_READABLE, l, "bool"); // ファイルが読み取り可能かどうか
FileInfo(handle, FILE_IS_WRITABLE, l, "bool"); // ファイルが書き込み可能かどうか
- ファイルが共有フォルダにあるか、テキストファイル(文字データを含むファイル)か、バイナリファイル(テキスト以外のデータを含むファイル)か、CSVファイル(カンマ区切りの値を含むファイル)か、ANSIエンコード(ANSI文字コードでエンコードされたファイル)か、読み取り可能か、書き込み可能かをそれぞれ確認し、エキスパートログに出力します。
FileClose(handle)
- 最後に、FileClose関数を使用してファイルハンドルを閉じ、関連するリソースを解放します。ファイル操作が完了した後は、必ずファイルハンドルを閉じるようにすることが重要です。
解説4:OnStart関数の中3
else
// ファイルが開けなかった場合のエラーメッセージを出力
PrintFormat("%s file is not opened, ErrorCode = %d", InpFileName, GetLastError());
}
else
- if文の条件が満たされなかった場合に実行されるブロックを示します。ここでは、FileOpen関数がファイルハンドルを正常に返さなかった場合、つまりファイルが開けなかった場合に実行されます。
PrintFormat(“%s file is not opened, ErrorCode = %d”, InpFileName, GetLastError());
- PrintFormat関数は、指定された形式に従って文字列をフォーマットし、エキスパートログに出力します。
- %s
これはフォーマット指定子で、文字列を挿入する場所を示します。ここでは、InpFileName(ユーザーが指定したファイル名)が挿入されます。 - file is not opened
この固定文字列は、ファイルが開けなかったことを示すメッセージです。 - %d
これはフォーマット指定子で、整数を挿入する場所を示します。ここでは、GetLastError関数によって返されるエラーコードが挿入されます。 - GetLastError()
GetLastError関数は最後に発生したエラーコードを取得する関数です。これにより、ファイルが開けなかった原因を特定するための情報が得られます。
この部分のコードは、ファイルを開けなかった場合にエラーメッセージをエキスパートログに出力し、エラーの原因を確認できるようにします。
解説5:オリジナル関数であるFileInfo関数の定義1
void FileInfo(const int handle, const ENUM_FILE_PROPERTY_INTEGER id,
long l, const string type)
void FileInfo
const int handle
- ファイルハンドルを示す整数型の引数です。ファイルハンドルは、ファイル操作を行う際の識別子として使用され、FileOpen関数で取得します。
const
は、この引数が関数内で変更されないことを保証します。
const ENUM_FILE_PROPERTY_INTEGER id
- 取得するファイルプロパティの識別子を示す列挙型の引数です。ENUM_FILE_PROPERTY_INTEGERは、ファイルの様々なプロパティを示す定数のセットです。
※ENUM_FILE_PROPERTY_INTEGERについての詳細は↓の記事をご参照ください。
long l
const string type
この関数は、指定されたファイルハンドルとプロパティ識別子を使用してファイルのプロパティを取得し、プロパティの型に応じて適切にフォーマットして表示します。
解説6:オリジナル関数であるFileInfo関数の定義2
{
//--- プロパティ値を受け取る
ResetLastError(); // エラーコードをリセット
if((l = FileGetInteger(handle, id)) != -1) // プロパティ値の取得に成功したかどうか
{
//--- 値を受け取ったので、正しいフォーマットで表示する
if(!StringCompare(type, "bool"))
Print(EnumToString(id), " = ", l ? "true" : "false"); // 真偽値として出力
if(!StringCompare(type, "date"))
Print(EnumToString(id), " = ", (datetime)l); // 日付として出力
if(!StringCompare(type, "other"))
Print(EnumToString(id), " = ", l); // その他の形式として出力
}
else
// エラーが発生した場合のエラーメッセージを出力
Print("Error, Code = ", GetLastError());
}
プロパティ値を受け取る
ResetLastError(); // エラーコードをリセット
- ResetLastError
ResetLastError関数は最後に発生したエラーコードをリセットします。これにより、新しいエラーが発生した際に正確なエラーコードを取得できます。
if((l = FileGetInteger(handle, id)) != -1) // プロパティ値の取得に成功したかどうか
- if文で、FileGetInteger関数を使用して指定されたファイルハンドルとプロパティ識別子に基づいてプロパティ値を取得し、変数lに格納します。
- FileGetInteger(handle, id)
指定されたファイルハンドルとプロパティ識別子を使用して、ファイルのプロパティ値を取得します。 - != -1
プロパティ値の取得に成功した場合、-1ではない値が返されます。取得に失敗した場合は-1が返されます。
値を受け取ったので、正しいフォーマットで表示する
StringCompare関数とEnumToString関数は、それぞれ次のような役割を持つ関数です:
- StringCompare関数は、2つの文字列を比較し、それらが一致するかどうかを確認します。
- EnumToString関数は、列挙型の識別子を文字列に変換します。
if(!StringCompare(type, "bool"))
Print(EnumToString(id), " = ", l ? "true" : "false"); // 真偽値として出力
- StringCompare(type, “bool”)
typeが”bool”と一致するかどうかを確認します。一致する場合、真偽値としてプロパティを表示します。 - Print(EnumToString(id), ” = “, l ? “true” : “false”)
EnumToString(id)を使用してプロパティ識別子を文字列に変換し、lの値に基づいて”true”または”false”を表示します。 - 三項演算子:
三項演算子は、条件式 ? 真の場合の値 : 偽の場合の値
という形式で使用されます。この場合、lが真(0以外の値)であれば”true”、偽(0の値)であれば”false”を返します。
if(!StringCompare(type, "date"))
Print(EnumToString(id), " = ", (datetime)l); // 日付として出力
- StringCompare(type, “date”)
typeが”date”と一致するかどうかを確認します。一致する場合、日付としてプロパティを表示します。 - Print(EnumToString(id), ” = “, (dateTime)l)
EnumToString(id)を使用してプロパティ識別子を文字列に変換し、lをdateTime型にタイプキャストして日付として表示します。
if(!StringCompare(type, "other"))
Print(EnumToString(id), " = ", l); // その他の形式として出力
- StringCompare(type, “other”)
typeが”other”と一致するかどうかを確認します。一致する場合、その他の形式としてプロパティを表示します。 - Print(EnumToString(id), ” = “, l)
EnumToString(id)を使用してプロパティ識別子を文字列に変換し、lの値をそのまま表示します。
エラーが発生した場合のエラーメッセージを出力
else
Print("Error, Code = ", GetLastError());
- else
if文の条件が満たされなかった場合、つまりプロパティ値の取得に失敗した場合に実行されます。 - Print(“Error, Code = “, GetLastError())
エラーコードをエキスパートログに出力します。GetLastError関数を使用して、最後に発生したエラーコードを取得します。
この部分のコードは、FileGetInteger関数を使用してファイルプロパティを取得し、その値を適切な形式で表示します。プロパティの取得に失敗した場合は、エラーメッセージをログに出力します。
コメント