//+------------------------------------------------------------------+//| Demo_FolderClean.mq4 |//| Peter Konow |//| https://www.mql5.com |//+------------------------------------------------------------------+#property copyright"Peter Konow"#property link"https://www.mql5.com"#property version"1.00"#property strict//+------------------------------------------------------------------+//Данный скрипт, сразу после загрузки должен стереть все содержимое //папки "1\\" внутри директории "Files".//Однако, если хэндл поиска, открытый сразу после запуска скрипта функцией//"FileFindFirst()" не закрыт, то скрипт не сможет стереть папку "1\\".//Данный скрипт создан для демонстрации взаимосвязи закрытия хэндла поиска//возвращаемого функцией "FileFindFirst()" и успешной работы функции "FolderClean()".//+------------------------------------------------------------------+//| Script program start function |//+------------------------------------------------------------------+voidOnStart()
{
//---- Переменная необходимая для функции "FileFindFirst()" string file_name;
//-----------------------------//Открываем поиск внутри папки "1\\".//-----------------------------long search_handle=FileFindFirst("1\\",file_name);
//--- проверим, успешно ли отработала функция FileFindFirst() if(search_handle!=INVALID_HANDLE)
{
int i = 0;
//--- в цикле проверим являются ли переданные строки именами файлов или директорий do
{
ResetLastError();
//--- если это файл, то функция вернет true, а если директория, то функция генерирует ошибку ERR_FILE_IS_DIRECTORY FileIsExist(file_name);
PrintFormat("%d : %s name = %s",i,GetLastError()==ERR_FILE_IS_DIRECTORY ? "Directory" : "File",file_name);
i++;
}
while(FileFindNext(search_handle,file_name));
//--- закрываем хэндл поиска FileFindClose(search_handle);
}
elsePrint("Files not found!");/**///-----------------------------//Переходим к очищению папки "1\\" и ее последующему стиранию.//-----------------------------if(!FolderClean("1\\"))
//--- Очищаем папку.Print("FolderClean Error ",GetLastError());
else
{//--- Стираем папку.if(!FolderDelete("1\\"))
Print("FolderDelete Error ",GetLastError());
elsePrint("Folder was cleaned and removed");
}
}
//+------------------------------------------------------------------+
後ほど、問題を再現したスクリプトを掲載します。
問題がどうにか解決したら、すべてを詳しく説明します。
1. ハンドルはFileClose関数にのみ必要です。ファイルを開けない。私より先に作られたものです。コピーして削除しているだけです。ハンドルがないので、閉じることができない。
2.コピー(FileCopy)、移動(FileMove)には、ファイルハンドルは必要ありません。ドキュメントを見てください。
3. FileOpen関数を使って他の人が作成したファイルを開くと、そのハンドルが取得できない。どのハンドルになるかは全く未定です。彼のものかもしれないし、まったく別のものかもしれない。他人のファイルのハンドルを取得して、コピー操作の後にFileCloseできるようにしようとしたのです。うまくいかなかった。
4.コピーする場合は、ハンドルは不要です。問題なくコピーできています。しかし、そのファイルは自動的にコピー用に開かれます。さらに、ハンドルがないので、FileCloseで閉じることもできません。コピーしたファイルを消去した後、FolderCleanが動作しないのはこのためと思われます。
5.コピーした後、ファイルが開いていないことをどうやって確認するのですか?FileOpen関数で明示的に開いたわけではなく、一緒にコピーされていた、つまり開いているということです。そのため、コピーした後でも、消去した後でも、開いたままになっています。おそらく。
ファイルハンドルは、ファイルのクローズだけでなく、ファイルの読み書き、指定行からの読み込みや指定行への書き込みのためのファイルポインタの管理にも必要である。ファイルハンドルを必要とする他の関数については、ドキュメントに記載されています。
2.ファイルをコピーしたり移動したりするには、そのファイルへのハンドルが必要だということを伝えられませんでしたか?何か勘違いしているようですね。
ファイルを開く場合、誰がいつ作ったものであっても、FileOpenが実行されると、そのハンドルが取得されます。
ハンドルとは何かを誤解しているのでは?実験用に2つのファイルを用意し、書き込み用に開いて、ハンドルを取得することができます。1つずつ異なることになります。次に、これらのファイルを開く順序を逆にすると、同じハンドルが表示されますが、それらは異なるファイルに属しています。第二の選択肢:ファイルを開き、ハンドル=1を取得し、そのファイルを閉じ、別のファイルを開く...。となり、もう一方のファイルのハンドルも「=1」になります。
ハンドルは、プログラム内部のファイルの番号付けであり、ファイルの内容やその他の属性とは関係がありません。
4.コピー中はファイルを開きません。また、あるファイルを読み込んでコピーし、その内容をすべて別のファイルに書き込む場合、それらのファイルのハンドルは、それらのファイルをさらに操作するために適切な変数に入れなければなりません。
5.ファイルのコピー中には数ミリ秒の時間がかかることがありますが、これはちょうどファイルをディスクに保存するのにかかる時間と同じです。そこから先は、空を飛ぶ鳥のように自由である...。何も起こらない可能性はない。
問題が完全に解決したことを報告します!(笑)
その理由は
ファイル階層のコピーを配列に構築する際、使用可能なファイルナビゲータに再現するために、特別な関数がFileFindFirst()とFileFindNext()を使用してこの階層を読み取ります。
当初は、各フォルダーをスキャンした後、ループの最後でFileFindClose()関数を 呼び、特定のフォルダーごとに検索ハンドルを閉じていました。
明らかに、ファイル階層を読み込む関数で長く複雑な操作をしていたため、誤ってこのエントリFileFindClose()を消してしまい、気がつかなかったのです。フォルダの名前を変更するまでは、ナビゲータのパフォーマンスには影響がありませんでした。そこからが問題だった。
ファイルは、この場合、全く関係ないことがわかった。もちろん、何もしていなくても閉めなければならないということを学んだのは、とても有意義なことです。今後は、同じ失敗をしないようにします。
一般に、私のFolderClean()関数が機能しなかった理由は、この関数を使うずっと前のプログラムの初期化段階で、別の関数がフォルダをスキャンした後にFileFindFirst()検索ハンドルを閉じていなかったからです。
結果的には、これらが関係しているのですが......。
この問題を再現するスクリプトを作ったのですが、このスクリプトではなぜかこの問題が再現されません。つまり、私のプログラムでは、"FileFindClose(search_handle) "という行を追加/削除すると問題に影響しますが、スクリプトでは、なぜか影響しないのです。
以下にスクリプトを添付します。Filesフォルダの中に「1」というフォルダを作り、そこに他のフォルダやファイルを入れてください。スクリプトを読み込むと、フォルダが消去されるはずです。 FileFindClose(search_handle)" という行をコメントアウトしてもフォルダは消去されますが、私のプログラムでは、この行なしでフォルダは消去されません。理由は定かではない。