MQL5Book/Scripts/p4/FileCursor.mq5
super.admin 1c8e83ce31 convert
2025-05-30 16:09:41 +02:00

203 lines
7.1 KiB
MQL5

//+------------------------------------------------------------------+
//| FileCursor.mq5 |
//| Copyright 2021, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include "..\..\Include\PRTF.mqh"
#include "..\..\Include\StructPrint.mqh"
const string fileraw = "MQL5Book/cursor.raw";
const string filetxt = "MQL5Book/cursor.csv";
const string file100 = "MQL5Book/k100.raw";
//+------------------------------------------------------------------+
//| Produce a string with file current position, and EOF, EOL flags |
//+------------------------------------------------------------------+
string FileState(int handle)
{
return StringFormat("P:%I64d, F:%s, L:%s",
FileTell(handle),
(string)FileIsEnding(handle),
(string)FileIsLineEnding(handle));
}
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
int handle;
Print("\n * Phase I. Binary file");
// create new file or open existing one for appending data
// the file will grow a bit on every start
handle = PRTF(FileOpen(fileraw, FILE_BIN | FILE_WRITE | FILE_READ));
Print(FileState(handle));
// moving file cursor to the end ensures that we will append data,
// not overwrite it from very beginning
PRTF(FileSeek(handle, 0, SEEK_END));
Print(FileState(handle));
// if file isn't empty, we can read existing data
// at specific position (relative or absolute)
// here we try to move for 1 int value back
if(PRTF(FileSeek(handle, -1 * sizeof(int), SEEK_CUR)))
{
Print(FileState(handle));
// read day_of_year from MqlDateStruct previously stored in the file
PRTF(FileReadInteger(handle));
}
// write current timestamp (datetime is 8 bytes long)
datetime now = TimeLocal();
PRTF(FileWriteLong(handle, now));
Print(FileState(handle));
// try to step back for 4 bytes and read (this will fail)
PRTF(FileSeek(handle, -4, SEEK_CUR));
long x = PRTF(FileReadLong(handle));
Print(FileState(handle));
// if step back for 8 bytes, another read will succeed
PRTF(FileSeek(handle, -8, SEEK_CUR));
Print(FileState(handle));
x = PRTF(FileReadLong(handle));
PRTF((now == x));
// now write MqlDateTime structure (note how position will change)
MqlDateTime mdt;
TimeToStruct(now, mdt);
StructPrint(mdt);
PRTF(FileWriteStruct(handle, mdt)); // 32 = sizeof(MqlDateTime)
Print(FileState(handle));
FileClose(handle);
Print(" * Phase II. Text file");
srand(GetTickCount());
// create new or open existing text file for writing (re-writing) it
// from very beginning with CSV-data (Unicode) and then reading
handle = PRTF(FileOpen(filetxt, FILE_CSV | FILE_WRITE | FILE_READ, ','));
// '\n' will be replaced with '\r\n' automatically,
// note that the last element doesn't have a '\n'
string content = StringFormat(
"%02d,abc\n%02d,def\n%02d,ghi",
rand() % 100, rand() % 100, rand() % 100);
PRTF(FileWriteString(handle, content));
PRTF(FileSeek(handle, 0, SEEK_SET));
Print(FileState(handle));
// let's count lines by FileIsLineEnding flag
int lineCount = 0;
while(!FileIsEnding(handle))
{
PRTF(FileReadString(handle));
Print(FileState(handle));
// FileIsLineEnding is also true if FileIsEnding is true and
// there is no trailing '\n'
if(FileIsLineEnding(handle)) lineCount++;
}
FileClose(handle);
PRTF(lineCount);
Print(" * Phase III. Allocate large file");
// create new or reset existing file and expand it to 1Mbyte
handle = PRTF(FileOpen(file100, FILE_BIN | FILE_WRITE));
PRTF(FileSeek(handle, 1000000, SEEK_END));
// we need to write something at current position
PRTF(FileWriteInteger(handle, 0xFF, 1));
PRTF(FileTell(handle));
FileClose(handle);
}
//+------------------------------------------------------------------+
/*
Example outputs
+-----------------------+
First run:
* Phase I. Binary file
FileOpen(fileraw,FILE_BIN|FILE_WRITE|FILE_READ)=1 / ok
P:0, F:true, L:false
FileSeek(handle,0,SEEK_END)=true / ok
P:0, F:true, L:false
FileSeek(handle,-1*sizeof(int),SEEK_CUR)=false / INVALID_PARAMETER(4003)
FileWriteLong(handle,now)=8 / ok
P:8, F:true, L:false
FileSeek(handle,-4,SEEK_CUR)=true / ok
FileReadLong(handle)=0 / FILE_READERROR(5015)
P:8, F:true, L:false
FileSeek(handle,-8,SEEK_CUR)=true / ok
P:0, F:false, L:false
FileReadLong(handle)=1629683392 / ok
(now==x)=true / ok
2021 8 23 1 49 52 1 234
FileWriteStruct(handle,mdt)=32 / ok
P:40, F:true, L:false
* Phase II. Text file
FileOpen(filetxt,FILE_CSV|FILE_WRITE|FILE_READ,',')=1 / ok
FileWriteString(handle,content)=44 / ok
FileSeek(handle,0,SEEK_SET)=true / ok
P:0, F:false, L:false
FileReadString(handle)=08 / ok
P:8, F:false, L:false
FileReadString(handle)=abc / ok
P:18, F:false, L:true
FileReadString(handle)=37 / ok
P:24, F:false, L:false
FileReadString(handle)=def / ok
P:34, F:false, L:true
FileReadString(handle)=96 / ok
P:40, F:false, L:false
FileReadString(handle)=ghi / ok
P:46, F:true, L:true
lineCount=3 / ok
* Phase III. Allocate large file
FileOpen(file100,FILE_BIN|FILE_WRITE)=1 / ok
FileSeek(handle,1000000,SEEK_END)=true / ok
FileWriteInteger(handle,0xFF,1)=1 / ok
FileTell(handle)=1000001 / ok
+-----------------------+
Second run:
* Phase I. Binary file
FileOpen(fileraw,FILE_BIN|FILE_WRITE|FILE_READ)=1 / ok
P:0, F:false, L:false
FileSeek(handle,0,SEEK_END)=true / ok
P:40, F:true, L:false
FileSeek(handle,-1*sizeof(int),SEEK_CUR)=true / ok
P:36, F:false, L:false
FileReadInteger(handle)=234 / ok
FileWriteLong(handle,now)=8 / ok
P:48, F:true, L:false
FileSeek(handle,-4,SEEK_CUR)=true / ok
FileReadLong(handle)=0 / FILE_READERROR(5015)
P:48, F:true, L:false
FileSeek(handle,-8,SEEK_CUR)=true / ok
P:40, F:false, L:false
FileReadLong(handle)=1629683397 / ok
(now==x)=true / ok
2021 8 23 1 49 57 1 234
FileWriteStruct(handle,mdt)=32 / ok
P:80, F:true, L:false
* Phase II. Text file
FileOpen(filetxt,FILE_CSV|FILE_WRITE|FILE_READ,',')=1 / ok
FileWriteString(handle,content)=44 / ok
FileSeek(handle,0,SEEK_SET)=true / ok
P:0, F:false, L:false
FileReadString(handle)=34 / ok
P:8, F:false, L:false
FileReadString(handle)=abc / ok
P:18, F:false, L:true
FileReadString(handle)=20 / ok
P:24, F:false, L:false
FileReadString(handle)=def / ok
P:34, F:false, L:true
FileReadString(handle)=02 / ok
P:40, F:false, L:false
FileReadString(handle)=ghi / ok
P:46, F:true, L:true
lineCount=3 / ok
* Phase III. Allocate large file
FileOpen(file100,FILE_BIN|FILE_WRITE)=1 / ok
FileSeek(handle,1000000,SEEK_END)=true / ok
FileWriteInteger(handle,0xFF,1)=1 / ok
FileTell(handle)=1000001 / ok
*/
//+------------------------------------------------------------------+