搜索文件和文件夹
MQL5 允许你在终端沙盒、测试程序代理以及所有终端的公用沙盒中搜索文件和文件夹(有关沙盒的详细信息,参见章节介绍 处理文件)。如果你准确知道所需文件/目录的名称和位置,则使用 FileIsExist 函数。
long FileFindFirst(const string filter, string &found, int flag = 0)
该函数根据传递的筛选器开始搜索文件和文件夹。筛选器可包含在沙盒中的子文件夹组成的路径,且必须包含要搜索的文件系统元素的确切名称或名称模式。filter 参数不能为空。
模板是包含一个或多个通配符字符的字符串。有两种这样的字符:星号 ('*') 可替换任何数量的任何字符(包括零),而问号 ('?') 可替换一个任意字符。例如,筛选器 "*" 将查找所有文件和文件夹,而 "???.*" 将仅查找名称长度不超过 3 个字符的文件和文件夹,可以选择包含扩展名。扩展名为 "csv" 的文件可通过 "*.csv" 筛选器查找(但需注意,文件夹也可能有扩展名)。筛选器 "*." 查找没有扩展名的元素,而 ".*" 查找没有名称的元素。然而,对此应记住以下两点。
在很多版本的 Windows 中,为文件系统元素生成两种名称:长名称(默认名称,最多 260 个字符)和短名称(继承自 MS-DOS 的 8.3 格式)。如果长名称超过 8 个字符或扩展名长于 3,则自动根据长名称生成第二种短名称。如果没有软件使用短名称,则可以在系统上禁用短名称生成,但通常情况下是启用的。
搜索文件时会同时搜索这两种类型的名称,这就是为什么返回的列表咋一看可能包含非预期元素的原因。尤其是由系统根据长名称生成的短名称始终在点号前面包含一个初始部分,最多长 8 个字符。可能偶然会找到具有期望模式的匹配项。
如果你需要查找具有若干个扩展名的文件,或名称中包含无法用单一模式概括的不同片段的文件,则必须以不同的设置重复若干次搜索过程。
搜索仅在特定文件夹中执行(如果筛选器中没有路径,则在根文件夹或在沙盒中,如果筛选器包含路径,则在指定文件夹中),不包括子目录。
搜索不区分大小写。例如,请求搜索 "*.txt" 文件也将返回扩展名 "TXT"、"Txt" 之类的文件。
如果找到具有匹配名称的文件或文件夹,则该名称被放在输出参数 found 中(需要一个变量,因为结果通过引用传递),并且函数返回一个搜索句柄:这将需要被传递给 FileFindNext 函数以继续对匹配项迭代(如果有很多匹配项)。
在 found 参数中,仅返回名称和扩展名,不会返回筛选器中可能已经指定的路径(文件夹层次结构)。
如果找到的项目是一个文件夹,会在其名称右侧追加 '\'(反斜杠)字符。
flag 参数允许在当前终端副本的本地工作文件夹(值 0)或所有终端的公用文件夹(值 FILE_COMMON)之间选择搜索区域。在测试程序中执行 MQL 程序时,其本地沙盒 (0) 位于测试程序代理目录中。
搜索过程完成后,应通过调用 FileFindClose(参见下文)来释放收到的句柄。
bool FileFindNext(long handle, string &found)
该函数继续以 FileFindFirst 函数开始搜索文件系统的适当元素。第一个参数是从 FileFindFirst 接收到的描述符,据此应用所有先前搜索条件。
如果找到下一个元素,则其名称通过自变量 found 传递给调用代码,然后函数返回 true。
如果没有更多元素,则函数返回 false。
void FileFindClose(long handle)
该函数可关闭因调用 FileFindFirst 而接收到的搜索描述符。
搜索过程完成后,必须调用该函数以释放系统资源。
举个例子,我们看看脚本 FileFind.mq5。在前面的章节中,我们测试了用于在 MQL5/Files/MQL5Book 目录中创建文件的很多其它脚本。请求所有这种文件的列表。
void OnStart()
|
即使你已清除该目录,你也仍然可以将随本书提供的各种编码的样本文件复制到其中。因此脚本 FileFind.mq5 应至少输出以下列表(枚举顺序可能有变化):
ansi1252.txt
|
为简化搜索过程,该脚本包含了辅助函数 DirList。这个辅助函数包含对内置函数的所有必要调用,还有一个用于构建具有匹配筛选器的元素列表的字符串数组的循环。
bool DirList(const string filter, string &result[], bool common = false)
|
我们利用该辅助函数来请求本地沙盒中目录的列表。为此,我们假定目录通常没有扩展名(理论上,并非总是如此,因此,如果程序员希望,应实施更严格的子文件夹列表请求)。无扩展名元素筛选器是 "*."(你可以使用 Windows shell 命令 dir "dir *." 进行检查)。但是,该模板在 MQL5 函数中会导致错误 5002 (WRONG_FILENAME)。因此,我们将指定一个更“模糊”的模板 "*.?":它表示没有扩展名或扩展名为 1 个字符的元素。
void OnStart()
|
在我的 MetaTrader 5 实例中,脚本找到两个文件夹 "MQL5Book\" 和 "Tester\"。如果你运行过先前的测试脚本,你应该也会有第一个文件夹。