处理文件

几乎所有程序都要使用数据输入输出。我们已经知道,MQL 程序可通过 输入变量 来接收设置,并将信息输出到日志,因为我们在几乎所有测试脚本中均使用日志。但在大多数情况下,这还不够。

例如,程序自定义的很大一部分涉及的数据量无法通过输入参数容纳。程序可能需要与某些外部分析工具集成,例如,以标准或特殊格式上传市场信息,处理这些信息并以新的格式加载到终端,尤其是作为交易信号加载,交易信号是一系列神经网络权重或决策树系数。此外,为 MQL 程序保持一份单独的日志可能会为我们提供方便。

文件子系统为此类任务提供了最普遍的方案。MQL5 API 提供了用于处理文件的各种函数,包括用于创建、删除、搜索、编写和读取文件的函数。我们将在本章中研究所有这些函数。

在 MQL5 中,所有文件操作均限制在磁盘上的一个特殊区域,称为沙盒。这样做是出于安全原因,避免 MQL 程序被用于不良目的,损害你的计算机或操作系统。

高级用户可使用特殊措施免除这一限制,对此我们将稍后再讨论。但这应仅在特殊情况下执行,且要遵守预防措施并自行承担全部责任。

对于计算机上安装的终端的每个实例,沙盒根目录位于 <terminal_data_folder>/MQL5/Files/。从 MetaEditor,可以使用 File -> Open Data Folder 命令打开数据文件夹。如果你对计算机有充分的访问权限,则该目录通常处于与终端安装所在位置相同的目录。如果你没有要求的权限,则路径可能象是这样:

X:/Users/<user_name>/AppData/Roaming/MetaQuotes/Terminal/<instance_id>/MQL5/Files/

其中 X 是安装系数的盘符,<user_name> 是 Windows 用户登录名,<instance_id> 是终端实例的唯一标识符。Users 文件夹也具有别名 "Documents and Settings"。

请注意,如果是通过 RDP(远程桌面协议)远程连接到计算机,即使你有管理员权利,终端也将始终使用 Roaming 文件夹及其子文件夹。

别忘了,数据目录中的 MQL5 文件夹是存储所有 MQL 程序的位置:包括它们的源代码和编译的 ex5 文件。每种类型的 MQL 程序,包括指标、EA 交易、脚本及其它程序,都在 MQL5 文件夹中有专门的子文件夹。因此,工作文件的 Files 文件夹与它们并列存在。

除了在计算机上的每个终端副本的这个单独沙盒外,还有一个所有终端的共享沙盒:其路径穿过 Windows 用户的主文件夹,可能因操作系统版本而不同。例如,在标准安装的 Windows 7、8 和 10 中,该路径象是这样:

X:/Users/<user_name>/AppData/Roaming/MetaQuotes/Terminal/Common/Files/

同样,该文件夹可轻松通过 MetaTrader 访问:运行命令 File -> Open Shared Data Folder,即可进入 Common 文件夹。

某些类型的 MQL 程序(EA 交易和指标)不仅可以在终端中执行,而且可以在测试程序中执行。运行 MQL 程序时,共享沙盒保持可访问,并且使用测试代理中的一个文件夹代替单个实例沙盒。一般如下所示:

X:/<terminal_path>/Tester/Agent-IP-port/MQL5/Files/

这在 MQL 程序本身内可能不可见,即所有文件函数均以完全相同的方式运行。然而,从用户角度,可能会觉得有点问题。例如,如果程将其工作结果保存到一个文件,在运行完成后,该文件将从测试程序的代理文件夹中删除(好像该文件从未被创建过一样)。这一例行方法旨在防止一个程序的潜在有价值数据被泄露进入可能稍后某个时间在该相同代理上进行测试的另一个程序中(尤其是由于代理是可以共享的)。提供了其它技术用于将文件传输给代理并从代理将结果返回至终端,对此我们将在本书第五章讨论。

要规避沙盒限制,可以使用 Windows 向系统对象赋予符号链接的功能。就我们的情况而言,连接(接合)最适合于在本地计算机上重定向文件夹访问。它们使用以下命令(即 Windows 命令行)创建:

mklink /J new_name existing_target

new_name 参数表示将指向真实文件夹 existing_target 的新的虚拟文件夹的名称。

要创建到沙盒外的外部文件夹的连接,建议在 MQL5/Files 内创建一个专用文件夹,例如 Links。然后,在进入该文件夹之后,可以通过选择 new_name 并将沙盒外面的真实路径替换为 existing_target 来执行上述命令。例如,以下命令将会在文件夹 Links 中创建一个名为 Settings 的新链接,该链接将提供对 MQL5/Presets 文件夹的访问:

mklink /J Settings "..\..\Presets\"

相对路径 "..\..\" 假定该命令在指定的 MQL5/Files/Links 文件夹中执行。两个点的组合 ".." 表示从当前文件夹转到父文件夹。如果指定两次,则该组合指示在路径层次中上移两级。因此,目标文件夹 (existing_target) 将生成为 MQL5/Presets。但在 existing_target 参数中,你也可以指定一个绝对路径。

你可以象常规文件一样删除符号链接(当然了,你应首先确保删除的是左下角带箭头图标的文件夹(即链接),而非原始文件夹)。建议不再需要访问沙盒外资源时立即删除链接。事实是,创建的虚拟文件夹对所有 MQL 程序可用,而不只是对你的程序可用,无法预测其他人的程序会如何使用这一附加的自由权限。

本章很多章节均在讨论文件名。它们作为文件系统元素标识符,具有类似规则,包括某些限制。

请注意,文件名不能包含在文件系统中扮演特殊角色的某些字符 ('<', '>', '/', '\\', '"', ':', '|', '* ', '?'),以及代码为 0 至 31 (含)的任何字符。

以下文件名也被保留用于操作系统中的特殊用途,不能使用:CON、PRN、AUX、NUL、COM1、COM2、COM3、COM4、COM5、COM6、COM7、COM8、COM9、LPT1、LPT2、LPT3、LPT4、LPT5、LPT6、LPT7、LPT8、LPT9。

需要注意的是,Windows 文件系统并不区分不同大小写字母之间的基本差异,因此诸如 "Name"、"NAME" 以及 "name" 等名称均指同一元素。

Windows 允许将反斜杠 '\\' 和正斜杠 '/' 用作路径要素(子文件夹和文件)之间的分隔符字符。然而,在 MQL5 字符串中,反斜杠需要进行转义(实际上写两次),因为 '\' 字符本身特殊:它用于构造控制字符系列,诸如 '\r'、'\n'、'\t' 等等(参见章节 字符类型)。例如,以下路径等效:"MQL5Book/file.txt" 和 "MQL5Book\\file.txt"。

点字符 '.’ 作为名称与扩展名之间的分隔符。如果一个文件系统元素在其标识符中有多个点,则最右侧点的右侧部分是扩展名,而其左侧的所有部分均为名称。标题(点之前)或扩展名(点之后)可以为空。例如,没有扩展名的文件名是“text”,而没有名称(仅有扩展名)的文件是 ".txt"。

Windows 中路径和文件名的总长度有限制。同时,为管理 MQL5 中的文件,应考虑沙盒路径将被添加到其路径和名称,即将为 MQL 函数调用中文件对象的名称分配更少的空间。默认情况下,总体长度限值是系统常量 MAX_PATH,等于 260。从 Windows 10 (build 1607) 开始,可将该限值增加到 32767。为此,你需要将以下文本保存为一个 .reg 文件,并通过将其添加到 Windows 注册表来运行该文件。
 
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem]
"LongPathsEnabled"=dword:00000001
 
对于其它版本的 Windows,你可以使用命令行替代方法。尤其是你可以使用上面讨论过的连接(通过创建具有短路径的虚拟文件夹)来缩短路径。你还可以使用 shell 命令 -subst,如 subst z: c:\very\long\path(详见 Windows 帮助)。