MQL5 编程基础: 文件(基础篇)
📘

MQL5 编程基础: 文件(基础篇)

第 1/3 篇

◍ MT5 里用文件先搞懂这几个坑

MQL5 里做文件读写,和常见脚本语言差别不小。MT5 把文件访问锁在专属目录里,默认只能碰 MQL5/Files 下的东西,想直接写 C 盘根目录会被终端拦掉,这是很多新手第一次跑文件代码就报错的原因。 终端对文件函数有显式权限位要求。打开文件时必须在 Open() 里带 FILE_READFILE_WRITEFILE_BIN 等标志,漏掉一个就可能返回无效句柄,而 GetLastError() 会给出 5004(文件未打开)这类具体码,比盲猜强。 官方示例帖自 2016-12-28 发布以来在站内有 12514 次浏览、21 条讨论,说明文件模块虽小但踩坑面不窄。开 MT5 按 F4 进编辑器,新建脚本把下面代码贴进去,能在 MQL5/Files 里生成 test.txt 并写一行,立刻验证权限机制是否如所说。

MQL5 / C++
class="type">int h=FileOpen("test.txt",FILE_WRITE|FILE_TXT);
if(h!=INVALID_HANDLE){
   FileWriteString(h,"hello from mql5");
   FileClose(h);
}

MT5里文件读写到底能玩出哪些花样

MQL5 把文件操作拆得很细:文本文件能整篇读、能新建、能往末尾追加,也能精准改指定某行;带分隔符的版本则可直接跟数组互转,省掉手工解析的麻烦。 对于 UNICODE 与二进制,差别在编码和粒度——二进制模式能直接落变量、结构甚至结构数组,FileReadInteger 这类函数负责按字节定义长度读回,避免乱码。 共享文件夹和测试器内的文件访问是实盘与回测的分水岭:跨终端用文件交换数据时要显式声明共享访问标志,否则 EA 在另一个终端读到的可能是空壳。 想立刻验证,把下面这段放到脚本里跑一遍,看终端 Data 文件夹是否生成 test.txt 并写入三行。

MQL5 / C++
class="type">int h=FileOpen("test.txt",FILE_WRITE|FILE_TXT);
if(h!=INVALID_HANDLE){
   FileWriteString(h,"line1\n");
   FileWriteString(h,"line2\n");
   FileWriteString(h,"line3\n");
   FileClose(h);
}

「MQL5 文件操作到底用在哪」

和多数编程语言一样,MQL5 具备完整的文件处理能力。写 EA 或指标时,文件读写不算日常操作,但每个开发者迟早会撞上:自定义交易报告导出、把复杂参数存成专用配置文件、或者从外部读取财经日历类的行情数据,都绕不开它。 MQL5 标准库里文件相关函数覆盖打开、写入、读取、关闭、定位等全套动作。文档中列出的文件函数有 20 个以上,本文逐个配一个能直接跑的小任务来练手,不空讲接口。 外汇与贵金属市场杠杆高、滑点跳空频繁,任何依赖外部文件做决策的逻辑,都先在模拟盘验证文件读写的边界与异常,再上实盘。

◍ MT5 脚本怎么吃进本地文本

想在 MT5 里让 EA 或脚本读外部配置、信号记录,第一步是把文件丢进 MQL5/Files 夹。这个目录是平台刻意划出的沙箱:文件函数只能碰这里,完整系统路径一律不可见,能挡掉第三方指标偷偷删你盘上文件或扒隐私的可能。 建个 test.txt 放进去,写两三段 ANSI 编码的纯文本。注意 Windows 默认隐藏扩展名,建议先打开「显示扩展名」避免存成 test.txt.txt 这种坑。MQL5 侧用 FileOpen 开文件,第二个参数必须按位或上 FILE_READ、FILE_TXT、FILE_ANSI——缺了 TEXT 或 ANSI 标志,读出来的中文或符号会乱码。 FileOpen 返回的是 int 句柄而不是文件名本身。后续所有读写关闭动作都靠这个句柄,等于给文件发了张临时门禁卡。下面这段是单行的极简读法:

int h=FileOpen("test.txt",FILE_READFILE_ANSIFILE_TXT);

if(h==INVALID_HANDLE){ Alert("打开文件错误"); return; } string str=FileReadString(h); Alert(str); FileClose(h); 逐行拆:第1行拿句柄,失败返回 INVALID_HANDLE;2-4行判错直接弹窗退出;第5行 FileReadString 读一行;第6行弹窗显示;第7行关文件释放句柄。若 test.txt 正被 Excel 独占,MT5 这边会开失败,但被记事本开着通常还能读。 真实场景里文件行数往往未知,硬调三次 FileReadString 不靠谱。用 FileIsEnding 配合 while 循环扫到末尾才停,下面这个函数能整文件倒进警报窗,做文件类实验直接复用: void ReadFileToAlert(string FileName){

int h=FileOpen(FileName,FILE_READFILE_ANSIFILE_TXT);

if(h==INVALID_HANDLE){ Alert("打开文件错误"); return; } Alert("=== 开始 ==="); while(!FileIsEnding(h)){ string str=FileReadString(h); Alert(str); } FileClose(h); } void OnStart(){ ReadFileToAlert("test.txt"); } 拆关键行:FileIsEnding(h) 到 EOF 返 true,取反即「还没读完就继续」;循环体内每次读一行并 Alert,跑完自动关句柄。实测三行文本会依次弹出「=== 开始 ===」+三行内容。外汇与贵金属交易涉及高杠杆高风险,任何文件读取逻辑上线前请在模拟盘验证句柄泄漏与编码问题。

MQL5 / C++
class="type">int h=FileOpen("test.txt",FILE_READ|FILE_ANSI|FILE_TXT);
if(h==INVALID_HANDLE){
   Alert("打开文件错误");
   class="kw">return; 
}
class="type">class="kw">string str=FileReadString(h);
Alert(str);
FileClose(h);
class="type">void ReadFileToAlert(class="type">class="kw">string FileName){
   class="type">int h=FileOpen(FileName,FILE_READ|FILE_ANSI|FILE_TXT);
   if(h==INVALID_HANDLE){
      Alert("打开文件错误");
      class="kw">return;
   }  
   Alert("=== 开始 ===");  
   while(!FileIsEnding(h)){
      class="type">class="kw">string str=FileReadString(h);
      Alert(str);  
   }
   FileClose(h);
class="type">void OnStart(){
   ReadFileToAlert("test.txt");
}

用 FileOpen 和 FileWrite 落盘文本

在 MT5 里新建一个文本文件,核心动作是调用 FileOpen() 并带上 FILE_WRITE 标志。上面这段脚本以 "test.txt" 为目标,组合 FILE_WRITEFILE_ANSIFILE_TXT 三个宏,拿到的句柄 h 若等于 INVALID_HANDLE 就直接弹窗报错并退出,避免后续空写。

拿到合法句柄后,循环 1 到 10 调 FileWrite(h, "Line-"+IntegerToString(i)),每调一次自动补一个换行,跑完文件里刚好是 10 行。注意若 test.txt 已存在,这种写法会把原内容整个清空,写重要日志前先确认路径里没有值钱数据。 FileWrite() 不限于两个参数。你可以传多个字符串变量,例如 FileWrite(h, "Line-", IntegerToString(i)),函数会把它们拼成同一行再落盘,不会中间插换行。 代码贴出来逐行看:int h=FileOpen(...) 是预先声明句柄;OnStart 里重新打开并判错;for 循环写十行;FileClose(h) 收尾并 Alert 提示。最后那行 FileWrite(h,"Line-",IntegerToString(i)) 是展示多参数拼行的写法,不在循环内。

MQL5 / C++
class="type">int h=FileOpen("test.txt",FILE_WRITE|FILE_ANSI|FILE_TXT);
class="type">void OnStart(){
   class="type">int h=FileOpen("test.txt",FILE_WRITE|FILE_ANSI|FILE_TXT);
   if(h==INVALID_HANDLE){
      Alert("打开文件错误");
      class="kw">return;
   }
   for(class="type">int i=class="num">1;i<=class="num">10;i++){
      FileWrite(h,"Line-"+IntegerToString(i));
   }
   FileClose(h);
   Alert("文件已创建");
}
FileWrite(h,"Line-",IntegerToString(i));

「把指针甩到末尾再落笔」

想在已有 test.txt 里追加内容又不抹掉旧数据,关键在打开模式。FileOpen() 必须同时带 FILE_READ 和 FILE_WRITE,文件若不存在就新建,若存在则原内容保留,但指针默认停在开头,直接写会从头部覆盖。 文件内部有个隐藏的“位置指针”,决定下一次读写的落点。打开时它自动归零,读写过程里随字节数自行滑动;你也可以强行挪动它,用的就是 FileSeek()。 追加逻辑很简单:写之前把指针丢到末尾。FileSeek(h,0,SEEK_END) 的意思是以文件末端为基准平移 0 字节,也就是贴在最后。这样 FileWrite() 写进去的行就接在原有内容后面。 下面这段代码每次跑都会往 test.txt 多塞一行“附加行”。在 MT5 里建个脚本跑两次,用记事本打开文件就能看到两行叠加,验证指针移位是否生效。

代码逐行看:FileOpen 用 READWRITEANSITXT 组合拿句柄;若返回 INVALID_HANDLE 弹窗报错并退出;FileSeek 把指针置尾;FileWrite 落“附加行”;FileClose 收尾并弹“已添加到文件”。
MQL5 / C++
class="type">int h=FileOpen("test.txt",FILE_READ|FILE_WRITE|FILE_ANSI|FILE_TXT);
FileSeek(h,class="num">0,SEEK_END);
class="type">void OnStart(){
   class="type">int h=FileOpen("test.txt",FILE_READ|FILE_WRITE|FILE_ANSI|FILE_TXT);
   if(h==INVALID_HANDLE){
      Alert("打开文件错误");
      class="kw">return;
   }
   FileSeek(h,class="num">0,SEEK_END);
   FileWrite(h,"附加行");
   FileClose(h);
   Alert("已添加到文件");
}

常见问题

默认只能读写终端的 Files 目录下子目录,路径要用 TerminalInfoString(TERMINAL_DATA_PATH) 拼接,别写绝对盘符路径。
用 FileOpen 时加 FILE_APPEND 标志,或 FileSeek 把指针甩到文件末尾再 FileWrite,就不会覆盖原内容。
可以,小布能读取你导出的本地文本,做AIGC诊断并在对应品种页提示异常模式,省去手动翻文件。
用 FileOpen 以 FILE_READ 打开,FileReadString 逐行吃进文本,解析后触发交易函数,注意处理编码和换行。
FILE_COMMON 指向所有终端共享的公共目录,适合多账户共用配置;普通标志只在当前终端数据目录,隔离更安全。