Complete MQL5 guide & code

MQL5 FileOpen Guide: Reading & Writing CSV Files in MetaTrader 5

Use MQL5 FileOpen flags, explicit UTF-8 encoding and delimiter checks to write and read a small CSV example. Learn the terminal and Common Files sandbox locations, overwrite versus append behavior, and why a sample file is not a trade-history export.

What this MQL5 guide covers

FileOpen returns a handle or INVALID_HANDLE; check write results as well as open results.

FILE_COMMON selects another allowed sandbox. It does not permit arbitrary filesystem access.

FILE_CSV defaults to a tab delimiter. Pass a comma explicitly when that is your file format.

This script writes synthetic six-column records, closes the file and reads it back. It places no trades and does not export account history.

FileOpen Function Signature and Bitmask Flags

MQL5 provides low-level file input/output through the FileOpen function. It opens files in text, binary, or delimited CSV mode, controlling access permissions and sharing policies.

FlagValue TypePurpose
FILE_READOpen flagOpens file for reading input data
FILE_WRITEOpen flagOpens file for writing (creates or overwrites existing file)
FILE_CSVFormat flagSpecifies comma/delimited text file where FileWrite inserts delimiters automatically
FILE_ANSIEncoding flagUses the selected code page; combine FILE_ANSI with CP_UTF8 explicitly for this UTF-8 example
FILE_COMMONLocation flagDirects path to shared Common\Files directory across all MT5 terminals
FILE_SHARE_READSharing flagAllows other applications or EAs to read the file simultaneously

Terminal Sandbox vs FILE_COMMON Directory

For security reasons, MetaTrader 5 isolates file operations within dedicated directory sandboxes. Without FILE_COMMON, files are written to [Terminal Data Folder]\MQL5\Files. In Strategy Tester the default root is the testing agent directory instead. These are MQL5 path restrictions, not a claim that OS tools cannot read the files.

FILE_COMMON selects the shared Common Files sandbox. Find the root with TerminalInfoString(TERMINAL_COMMONDATA_PATH), then its Files subfolder. External readers need the correct location, encoding and sharing permissions; concurrent writers still require coordination.

  • Local Sandbox: FileOpen("log.csv", FILE_WRITE | FILE_CSV); -> MQL5\Files\log.csv
  • Shared Directory: FileOpen("log.csv", FILE_WRITE | FILE_CSV | FILE_COMMON); -> Common\Files\log.csv
  • Subdirectories: You can specify relative subfolders such as "Data\\EURUSD.csv".

Reading CSV Records Row by Row

When reading a CSV file opened with FILE_CSV, each call to FileReadString(handle) reads the next token up to the delimiter or newline.

An end-of-file loop alone does not validate row width or data types. The example checks exactly six fields per row and logs strings, including the header. It targets the simple records it writes; it is not a general parser for quoted fields containing delimiters or embedded newlines.

Implementation details & mechanics

Core implementation pattern

Save this as a script in MQL5/Scripts. It writes a header and two explicitly synthetic quote records, then reads the file. Existing files are refused unless InpAllowOverwrite is enabled; enabling it replaces the entire file. The existence check is a convenience guard, not a concurrent-writer lock. For a real trade log, source data from confirmed transactions and define an append and recovery policy separately.

Error handling & safety rules

Every successful open must reach FileClose, including failure paths. Check FileWrite for zero and report the error; a partial file may remain after failure. FILE_READ | FILE_WRITE preserves an existing file, but appending also requires a successful FileSeek to SEEK_END. Write a header only when the file is empty. Flush or close before another reader consumes the file; this is not a transaction or crash-recovery guarantee.

MQL5 Code Implementation

//+------------------------------------------------------------------+
//|                                             FileOpenCSVGuide.mq5 |
//|                             Copyright 2026, Pineify Guides Series |
//|                                              https://pineify.app |
//+------------------------------------------------------------------+
#property copyright "Pineify Guides Series"
#property link      "https://pineify.app/mql5/fileopen-csv-guide"
#property version   "1.00"
#property script_show_inputs

//--- Input parameters
input string InpFileName = "pineify_csv_example.csv"; // CSV File Name
input bool   InpAllowOverwrite = false;         // Existing files are refused by default
input bool   InpUseCommonFolder = true;         // Use Shared Common\Files Folder

//+------------------------------------------------------------------+
//| Function: Write trade records to CSV                             |
//+------------------------------------------------------------------+
bool WriteTradeLogCSV(const string filename, bool useCommon)
  {
   if(!InpAllowOverwrite && FileIsExist(filename, useCommon ? FILE_COMMON : 0))
     {
      Print("Existing file refused: ", filename);
      return false;
     }
   int flags = FILE_WRITE | FILE_CSV | FILE_ANSI;
   if(useCommon)
      flags |= FILE_COMMON;

   // Open file for writing with comma ',' delimiter
   int fileHandle = FileOpen(filename, flags, ',', CP_UTF8);
   if(fileHandle == INVALID_HANDLE)
     {
      PrintFormat("Failed to open file %s for writing. Error: %d", filename, GetLastError());
      return false;
     }

   // 1. Write Header Row
   ResetLastError();
   bool wrote = FileWrite(fileHandle, "Timestamp", "Symbol", "Action", "Lots", "Price", "Comment") > 0;

   // 2. Write Data Rows
   if(wrote) wrote = FileWrite(fileHandle,
             TimeToString(TimeCurrent(), TIME_DATE|TIME_SECONDS),
             _Symbol,
             "SAMPLE_BUY",
             0.10,
             SymbolInfoDouble(_Symbol, SYMBOL_ASK),
             "Synthetic example only") > 0;

   if(wrote) wrote = FileWrite(fileHandle,
             TimeToString(TimeCurrent(), TIME_DATE|TIME_SECONDS),
             _Symbol,
             "SAMPLE_QUOTE",
             0.10,
             SymbolInfoDouble(_Symbol, SYMBOL_BID),
             "No order was sent") > 0;

   int writeError = GetLastError();
   // 3. Close File Handle even when a write fails
   FileClose(fileHandle);
   if(!wrote)
     {
      PrintFormat("CSV write failed: %d; a partial file may remain", writeError);
      return false;
     }
   PrintFormat("Successfully wrote CSV records to %s", filename);
   return true;
  }

//+------------------------------------------------------------------+
//| Function: Read and parse CSV file records                        |
//+------------------------------------------------------------------+
bool ReadTradeLogCSV(const string filename, bool useCommon)
  {
   int flags = FILE_READ | FILE_CSV | FILE_ANSI;
   if(useCommon)
      flags |= FILE_COMMON;

   int fileHandle = FileOpen(filename, flags, ',', CP_UTF8);
   if(fileHandle == INVALID_HANDLE)
     {
      PrintFormat("Failed to open file %s for reading. Error: %d", filename, GetLastError());
      return false;
     }

   Print("--- Reading CSV Data ---");
   int lineNum = 0;

   // Loop until end of file
   while(!FileIsEnding(fileHandle))
     {
      string cols[6];
      for(int i=0; i<6; ++i)
        {
         cols[i] = FileReadString(fileHandle);
         if(i<5 && (FileIsLineEnding(fileHandle) || FileIsEnding(fileHandle)))
           {
            PrintFormat("Short CSV row %d", lineNum+1);
            FileClose(fileHandle);
            return false;
           }
        }
      if(!FileIsLineEnding(fileHandle) && !FileIsEnding(fileHandle))
        {
         PrintFormat("Extra fields in CSV row %d", lineNum+1);
         FileClose(fileHandle);
         return false;
        }

      lineNum++;
      PrintFormat("Row %d: [%s] | Symbol: %s | Action: %s | Lots: %s | Price: %s | Note: %s",
                  lineNum, cols[0], cols[1], cols[2], cols[3], cols[4], cols[5]);
     }

   FileClose(fileHandle);
   PrintFormat("Finished reading %d rows from %s", lineNum, filename);
   return true;
  }

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
   // Demo: Write sample records, then read them back
   if(WriteTradeLogCSV(InpFileName, InpUseCommonFolder))
     {
      ReadTradeLogCSV(InpFileName, InpUseCommonFolder);
     }
  }

Copy this code into MetaEditor, save it in your MQL5 folder (Experts, Scripts, or Include), and compile with F7.

Generate custom MQL5 code with Pineify AI

Describe the trade execution, indicator calculations, risk management, or data processing logic you need. Pineify generates editable MQL5 source code. Review its logic, request a syntax check, and compile and test the final file in MetaEditor.

Frequently Asked Questions

Related MQL5 pages

Technical references

Risk and testing note

These educational examples require independent compilation and testing. A compile pass or an illustrative setting does not establish execution correctness or profitability. Any reported performance must be supported by reproducible data and test settings; past results do not predict future returns. Trading involves significant risk of loss. This content is not financial advice.