![【MQL4】文字列をバイナリーファイルとして保存する時のコツ。](https://celebpanda.com/wp/wp-content/uploads/2021/05/セレブパンダブログ用.jpg)
電化製品を無料で回収しますと言って巡回する方に、プリンタを回収してといったら、これは有料ですと言われ、だったら無料って言うなよと思ったセレブパンダだお。
本日は、ファイルの入出力のお話です。あまり馴染みがない人もいると思います。
こんなことに使えます。
バックテストではなくリアルティックの状態でアローを表示します。そのアローが出た価格や時間をファイルに出力して、後で分析したい。
リアルティックでアローを表示している。インジを消した時は、そのアローも消すが、再びインジをセットするとアローを復元して表示したい。
など、バックテストでは取れないロジックなどを保存しておくのに便利です。
ファイルに出力するので、そのままだとテキストエディタやメモ帳で開くと内容がわかってしまいます。
内容を簡単には知られたくない時には、ファイルのバイナリーモードにすると、テキストエディタでは読めない文字になります。
ただ、テキストのバイナリーモードでの扱いはポイントがあります。
それは、文字の長さを一定にしておくことです。バイナリーモードでは、ファイルに書き出した内容を読み取る時に、指定バイト数ずつ読み出します。
その時に、「好きです。」「ぼくはセレブパンダ」などと文字の長さが異なるとうまく読み出しができません。
そこで文字列はある一定の文字数で出力すると決めることで解決できます。
先ほどの場合、20バイトで文字は書き出すとします。
「好きです。」→「好きです。 」
「ぼくはセレブパンダ」→「ぼくはセレブパンダ 」
と20バイトになるまで半角スペースを埋めて書き込むことで、テキストでもバイナリモードでのやり取りができます。
サンプル(書き込み)
バイナリーモードでのテキスト書き込みです。
これは、オブジェクトの名称に「arrowTrdLine」という名前のトレンドラインの、オブジェクト名、価格、説明と色をファイルに出力するサンプルです。
void doWriteTrendInfo(){
// ファイル名は拡張子をbinした。
string filename = Symbol() + "_" + WindowExpertName() + ".bin";
int handle ;
// バイナリーモードでファイルを開く。
handle=FileOpen(filename , FILE_READ|FILE_WRITE|FILE_BIN );
if (handle > 0) {
// ファイルの末尾に移動
bool bRtn = FileSeek(handle, 0, SEEK_END);
if (bRtn) {
for(int obj = ObjectsTotal() - 1; obj >= 0; obj--)
{
string obj_name=ObjectName(obj);
if(StringFind(obj_name,"arrowTrdLine",0)>=0)
{
string text=ObjectGetString(0,obj_name,OBJPROP_TEXT);
double price=ObjectGetDouble(0,obj_name,OBJPROP_PRICE,0);
long clr = ObjectGetInteger(0,obj_name,OBJPROP_COLOR);
FileWriteString(handle,RightPading(Symbol(),6 ) , 6 ); // 通貨ペア
FileWriteString(handle,RightPading(obj_name,22) , 22 ); // オブジェクト名
FileWriteDouble(handle,price,DOUBLE_VALUE); // 価格
FileWriteString(handle,RightPading(text,12 ) , 12 ); // オブジェクトの説明
FileWriteInteger(handle,clr,LONG_VALUE); // 色
}
}
}
FileClose(handle);
} else {
Print("ファイルオープンに失敗。",filename);
}
}
ここでポイントは、文字列は、指定のバイト数まで空白スペースを埋めています。
RightPading(Symbol(),6 )
がそれに該当します。
string RightPading(string aValue, int aDigits){
string result = aValue;
int length = StringLen(result);
if(length >= aDigits){
return(result);
}
for(int i = 0; i < aDigits - length; i++){
result = result + " ";
}
return(result);
}
この関数は、文字列が指定されたバイト数(aDigits)まで、半角スペースを右にうけてくれるものです。
サンプル(読み込み)
書き込んだ情報を読みだしてみるサンプルです。
void readHistogram(){
string filename = gFolder + Symbol() + "_" + WindowExpertName() + ".bin";
int filehandle ;
// ファイルの存在チェック
if ( FileIsExist(filename) != false ) {
filehandle=FileOpen(filename , FILE_READ|FILE_BIN );
FileSeek(filehandle,0,SEEK_SET);
int row = 0;
// 買いTickオブジェクトの生成
while( FileIsEnding(filehandle) == False) {
string symbolFile = FileReadString(filehandle, 6); //通貨ペア
StringReplace(symbolFile, " ", "");
string name = FileReadString(filehandle, 22); //オブジェクト名
StringReplace(name, " ", "");
double y = FileReadDouble(filehandle,DOUBLE_VALUE); // 価格
string text = FileReadString(filehandle,12); //オブジェクトの説明
StringReplace(text, " ", "");
int clr = FileReadInteger(filehandle,LONG_VALUE); //カラー
int n = StrToInteger(StringSubstr(text,1));
if (Symbol() == symbolFile)
{
}
row++;
}
FileClose(filehandle);
FileDelete(filename);
Print("対象件数=",row);
}
}
これは、先ほど、書き込んだファイルを読み込み、Printで内容を確認するサンプルです。
ポイントはテキストで書き出した値は、同じバイト数で取り出してやる所です。
string name = FileReadString(filehandle, 22);
先ほど、オブジェクト名は22バイトで書き出したので、読み込みも22バイト分で読みだしてやれば問題なく読むことができます。
参考にしてみてください。
では、まただお。