//+------------------------------------------------------------------+//| 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。
手柄是程序内文件的编号,它与文件的内容或其他属性无关。
4.在复制过程中,该文件不会被打开。如果你是通过读取一个文件并将整个内容写入另一个文件来进行复制的,这些文件的句柄应该放在适当的变量中,以便进一步操作这些文件。
5.一个文件在复制过程中可能需要几毫秒的时间,正好是将其保存到磁盘的时间。从那里,它就像天空中的鸟儿一样自由......。没有发生任何事情的机会。
我很高兴地报告,这个问题已经完全解决了!)
原因是。
当在数组中建立一个文件层次结构的副本时,为了在一个可用的文件导航器中再现它,一个特殊的函数使用FileFindFirst()和FileFindNext()读取这个层次结构。
最初,在每个文件夹被扫描后,在循环结束时调用FileFindClose()函数 以关闭每个特定文件夹的搜索句柄。
很明显,由于对读取文件层次的函数进行了长时间的复杂操作,我不小心抹掉了FileFindClose()这个条目,而没有注意到它。这并不影响我的导航仪的性能,直到我开始尝试重命名文件夹。这就是问题的开始。
事实证明,这些文件与本案完全没有关系。当然,我已经学会了它们必须被关闭,即使我没有对它们做任何事情,这非常有用。在未来,它将使我不会犯同样的错误。
总的来说,我的FolderClean()函数不工作的原因是,早在我使用它之前,在程序的初始化阶段,另一个函数在扫描文件夹后没有关闭FileFindFirst()的搜索句柄。
事实证明,这些事情是相关的...
我做了一个脚本来重现这个问题,但由于某些原因,在这个脚本中,这个问题没有重现。也就是说,在我的程序中添加/删除 "FileFindClose(search_handle) "一行确实会影响到这个问题,但在脚本中,由于某种原因,却没有影响。
我把脚本附在下面。在Files文件夹中创建一个文件夹 "1",并将任何其他文件夹或文件放在那里。如果你把 "FileFindClose(search_handle) "这行注释掉,脚本仍然会删除文件夹,但在我的程序中,如果没有这行,文件夹就不会被删除。原因并不清楚。