Lucrul cu fisiere . Partea I

December 31, 2009
By Bogdan Baltatu, MQLmagazine editor

[English version] [MQLmagazine.com in english] [Editia romaneasca]

In acest articol vom prezenta lucrul cu fisiere si directoare in MQL5.

Functiile care lucreaza cu fisierele in MQL5 sunt se pot imparti in 2 grupe:

  • Functii care se ocupa cu manevrarea si starea fisierelor
  • Functii care se ocupa cu cititul si scrisul in fisiere

In continuarea articolului o sa preiau fiecare grupa de functie in parte si o sa descriu cu exemple de cod functionalitatea functiilor.

Functii care se ocupa manevrarea si starea fisierelor

Aceste functii sunt cele care deschid , inchid , sterg , copiaza , forteaza scrierea , verifica existenta fisierelor si starea cursorului in cadrul fisierului. Mai jos sunt functiile le-am incadrat in aceasta categorie.

FileClose, FileCopy, FileDelete, FileFindClose, FileFindFirst, FileFindNext, FileFlush,
FileIsEnding, FileIsExist, FileIsLineEnding, FileMove, FileOpen, FileSeek, FileTell

Flags

O parte din functiile enumerate mai sus se folosesc de flaguri. Aceste flaguri (flags -ro. steaguri) sunt constante globale de tip integer definite in MQL5 si au rolul de a specifica modul de deschidere a fisierului (text,csv,ansi,binar), cat si tipurile de operatiuni care se fac asupra fisierului (citire/scriere).

In tabelul de mai jos se evidentiaza valoarea binara dar si valoarea zecimala a identificatorului deoarece sunt foarte importante pentru intelegerea functionarii flagurilor.

Valoare zecimala Valoare binara Identificator de flag Descriere
1 0000000000001 FILE_READ Fisier deschis pentru citire
2 0000000000010 FILE_WRITE Fisier deschis pentru scriere
4 0000000000100 FILE_BIN Acces de tip binar pentru citire scriere.(fara folosirea sirurilor)
8 0000000001000 FILE_CSV Fisier de tip CSV (Fisier text cu elemente separate de un separator)
16 0000000010000 FILE_TXT Fisier text
32 0000000100000 FILE_ANSI Fisier ANSI (simboluri pe un byte)
64 0000001000000 FILE_UNICODE Fisier UNICODE (simboluri pe doi bytes)
128 0000010000000 FILE_SHARE_READ Acces impartit pentru citire de mai multe programe
256 0000100000000 FILE_SHARE_WRITE Acces impartit pentru scriere de mai multe programe
512 0001000000000 FILE_REWRITE Posibilitatea de a rescrie fisierul cu functiile FileCopy si FileMove.
4096 1000000000000 FILE_COMMON Fisierul se afla in folderul comun pentru toate terminalele client MT5.

Comparand cu precedentul limbaj de la MetaQuotes , MQL4, se poate observa aparitia unor noi flaguri cum ar fi cele care dau posibilitatea deschiderii in fisierelor in alte moduri precum :  ANSI , text , UNICODE  dar si doua moduri noi de deschidere care permit scrierea si citirea in fisiere chiar daca ele sunt deschise de alte programe.

O noutate adusa ce cei de la MetaQuotes este deschiderea unor fisiere care se afla in folderul MQL5 si nu doar din terminal_directory\experts\files asa cum era posibil in MQL4.

Functiile care lucreaza cu fisiere pot accepta combinatii de flaguri dar aceste flaguri trebuie folosite cu grija deoarece de exemplu nu poti folosi FILE_TXT|FILE_BIN in acelasi timp pentru ca practic este imposibil sa deschizi acelasi fisier in 2 moduri. Voi detalia mai jos la functia FileOpen() folosirea corecta a flagurilor.

FileOpen
Functia FileOpen() sta la baza operatiilor cu fisiere deoarece nici nu se poate continua cu alte operatii daca nu se pot crea sau deschide fisiere.

1
2
3
4
int FileOpen(string file_name, //Numele fisierului
          int open_flags,  //Combinatie de flaguri
          short delimiter  //Delimitator (doar in cazul fisierelor CSV)
    );

Functia intoarce un intreg si acest intreg trebuie memorat intr-o variabila deoarece el va fi folosit ulterior pentru toate operatiile cu fisierul respectiv, el reprezentand practic referinta catre fisierul deschis sau creat.

Functia FileOpen() are dublu rol deoarece ea se foloseste si pentru deschiderea dar si pentru crearea fisierelor.

1
2
3
4
5
6
7
8
9
int m_handle=-1;
string m_filename="test.txt";
m_handle=FileOpen(m_filename,FILE_READ|FILE_TXT);
if (m_handle<0)
 {
    Print("Nu pot deschide fisierul.");
 }
else
 Print("Fisier deschis cu succes.");

Codul de mai sus deschide fisierul “test.txt” in modul text. Daca fisierul nu exista m_handle va deveni -1 ceea ce inseamna ca fisierul nu a fost deschis. (Logic ca nu poate fi deschis daca nu exista).
Daca dorim sa cream un fisier trebuie neaparat sa folosim FILE_WRITE deoarece flagul creeaza fisierul in acelasi timp. Fisierul creat se afla in folderul /MQL5/Files/. In versiunea beta , cea care exista in momentul scrierii articolului , fisierele nu se afla in folderul MQL5 de unde ati instalat platforma. Pentru a vedea exact unde se afla fisierele puteti folosi intr-un script urmatoarea linie:

1
Print(TerminalInfoString(TERMINAL_DATA_PATH));

Atentie mare la folosirea flagurilor , deoarece folosirea necorespunzatoare poate genera erori.

FileClose

1
2
3
void  FileClose(
   int  file_handle      // Handler de fisier
   );

Parametrul file_handle este cel returnat de functia FileOpen() , in exemplul de la FileOpen() numele parametrului nostru este m_handle. Este bine sa resetam acest parametru la -1 dupa ce inchidem fisierul deoarece daca vrem sa verificam daca este fisierul deschis putem sa ne uitam la valoarea lui m_handle. Functia FileClose() nu intoarce nici un rezultat ceea ce insemna , cel putin la nivel teoretic , ca functia se executa cu succes.

FileDelete

Functia sterge un fisier fie ca se afla in folderul local al terminalului , fie ca se afla in folderul comun pe care toate platformele MetaTrader5 il folosesc.

1
2
3
4
bool  FileDelete(
   string  file_name      // Numele fisierului care va fi sters
   int     common_flag=0  // Flag de localizare
   );

Al doilea parametru este optional. In caz ca el este FILE_COMMON functia va sterge fisierul din folderul impartit de toate platformele MetaTrader5 ; altfel, va sterge fisierul din statia locala.
Functia returneaza true daca operatiunea a fost executata cu succes sau false in caz de operatiunea a esuat.
Expertii MetaTrader pot fi rulati in timp real sau pot fi testati pe date istorice.Cand se testeaza expertii pe date istorice functiile care lucreaza cu fisiere nu mai folosesc folderul /MQL5/files ci /MQL5/tester.

FileCopy
Functia copiaza un fisier din folderul local sau folderul comun sub alt nume pastrand fisierul original.

1
2
3
4
5
6
bool  FileCopy(
       string  src_filename,       //Numele fisierului de copiat
       int     common_flag,       //Flagul de localizare
       string  dst_filename,      //Numele fisierului destinatie
       int     mode_flags          //Modul de acces
   );

Parametrul a doilea , common_flag , nu poate sa lipseasca si de aceea cand fisierul pe care dorim sa il copiem nu se afla in folderul comun tuturor platformelor MT5 se inlocuieste cu 0.
Parametrul mode_flags are doar 2 optiuni: FILE_REWRITE si/sau FILE_COMMON.
Daca fisierul destinatie exista si incercam sa copiem un fisier fara sa specificam FILE_REWRITE pentru parametrul ‘mode_flags’ atunci continutul fisierului sursa nu va exista in fisierul destinatie.

FileMove
Prototipul functiei este identic cu cel a functiei FileCopy(). Diferenta este ca functia FileMove copiaza fisierul sursa in alta locatie dar in acelasi timp sterge fisierul sursa. Practic functia poate fi folosita si pentru a redenumi un fisier deja existent.

FileFlush
Functia are rolul de a scrie pe disc datele care se afla in buffer.

1
2
3
void  FileFlush(
       int  file_handle      // Handler de fisier
       );

Functia are un singur parametru , acesta fiind referinta fisierului care rezulta in urma deschiderii/crearii fisierului cu FileOpen().
Pentru a intelege la ce foloseste FileFlush() trebuie sa intelegem modul de functionare a operatiunilor de scriere/citire in fisiere. Atunci cand un fisier este deschis informatia este copiata in memorie intr-un buffer , deoarece viteza memoriei este mult mai mare ca viteza discului. Este obligatoriu ca functia sa fie chemata la schimbarea operatiunii, de la citire la scriere si viceversa.

FileIsExist
Functia FileIsExist() verifica daca exista fisierul.

1
2
3
4
bool  FileIsExist(
       string  file_name,           // Numele fisierului
       int     common_flag=0    // Flag de localizare
       );

Primul parametru se refera la numele fisierului , iar al doilea parametru se refera la locul unde sa il caute.
Functia poate fi folosita pentru a limita erorile generate de FileOpen() in cazul in care fisierul care se doreste deschis nu exista.

FileTell
Functia returneaza pozitia curenta a pointerului intr-un fisier deschis.

1
2
3
int  FileTell(
       int  file_handle    // Handler de fisier
       );

Pozitia pointerului este exprimata in numarul de bytes de la inceputul fisierului.

FileIsEnding
Functia se foloseste pentru a se afla daca s-a atins sfarsitul fisierului.

1
2
3
bool  FileIsEnding(
       int  file_handle      // Handler de fisier
       );

Functia este necesara deoarece este foarte important sa stim cand s-a atins sfarsitul fisierului, de cele mai multe ori, cand fisierul este citit in intregime sau cand se cauta ceva in el.

FileIsLineEnding
Functia are acelasi prototip ca si functia FileIsEnding() numai ca ea returneaza true cand se atinge sfarsitul liniei.
Functia se poate folosi doar doar in cazul fisierelor text sau csv si sfasitul liniei este atunci cand se intalneste caracterul CR(Carriage Return) sau LF(Line Feed). Totusi, functia are unele probleme la momentul prezent la care este scris articolul.

FileSeek
Functia muta cursorul un numar de bytes de la pozitia specificata.

1
2
3
4
5
void  FileSeek(
       long                 file_handle      // Handler de fisier
       int                  offset,             // Numarul de bytes cu care se muta cursorul
       ENUM_FILE_POSITION   origin  // Pozitia de referinta
       );

Pozitia de referinta poate fi SEEK_SET(inceputul fisierului),SEEK_CUR(pozitia curenta),SEEK_END(sfarsitul fisierului). Numarul de bytes poate fi atat pozitiv cat si negativ deci cursorul se poate muta in ambele directii.

Ultimele trei functii pe care o sa le prezentam in acest articol sunt FileFindFirst() , FileFindNext() si FileFindClose().

FileFindFirst
Functia are rolul de a incepe cautarea unor fisiere in folderul local sau folderul comun cu un un filtru anume.

1
2
3
4
5
long  FileFindFirst(
       string   file_filter,                    // Filtrul dupa care caut
       string&  returned_filename,     // Numele fisierului gasit
       int      common_flag               // Flag de localizare
       );

Primul parametru , file_filter , reprezinta filtrul de cautare al fisierelor (wildcard).
Exemple de filtre:
- “*.*” – cauta toate fisierele;
- “*.txt” – cauta toate fisierele de tip text (a se citi “cu extensia .txt”)
- “test.*” – cauta toate fisierele cu numele “test” indiferent de extensia fisierului.
Functia FileFindFirst() intoarce o referinta a cautarii , fiecare cautare are o referinta unica.
Al doilea parametru , returned_filename , este de tip string si functia initiaza acest parametru cu numele primului fisier gasit in functie de criteriul dorit.

FileFindNext
Functia este asemanatoare cu FileFindFirst() numai ca prototipul este diferit.

1
2
3
4
bool  FileFindNext(
       long      search_handle,           // Referinta cautarii
       string&   returned_filename      // Numele fisierului gasit
   );

Functia continua o cautare inceputa cu FileFindFirst() (stie asta din primul parametru, referinta de cautare).
Functia intoarce in al doilea parametru urmatorul fisier care se potriveste cu filtrul cautarii. Intoarce true daca umple acest parametru cu un fisier valid ; daca nu reuseste, si asta se intampla la sfarsitul cautarii, intoarce false.

FileFindClose
Functia inchide referinta cautarii.

1
2
3
void  FileFindClose(
       long  search_handle      // Referinta cautarii
   );

Este necesar sa folosit functia deoarece numai asa putem sa eliberam resursele alocate la apelarea functiei FileFindFirst().

Prototipurile functiilor de mai sus pot fi schimbate de cei de la MetaQuotes deoarece in momentul scrierii articolului platforma si MetaEditor sunt in versiune beta. Daca gasiti o greseala in articol va rugam semnalati-o.

Leave a Reply