forked from rosh/MQL5Book
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
| |
| |
*/
| |
//+------------------------------------------------------------------+
|