203 lines
7.1 KiB
MQL5
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
|
|
|
|
*/
|
|
//+------------------------------------------------------------------+
|