Travailler avec des fichiers. - page 4

 

TheXpert:

OMG ! Là où se trouve la sortie, c'est un non-sens. C'est ainsi que l'on entend des affirmations telles que "la programmation orientée objet est plus rapide" ou "les indicateurs sont lents, nous devrions mettre l'ensemble du code dans Expert Advisor".

Je comprends que tout ne fonctionne pas comme prévu. Au moins, l'utilisation normale de FileFlush() devrait être plus rapide que FileClose().

Mais je continue à penser que nous ne devrions pas insérer de telles choses à l'intérieur des boucles, elles ne seront pas d'une grande aide de toute façon.

Et si j'ai bien compris l'exemple pour MQL4, l'appel de FileFlush() est placé entre deux boucles (ce qui me laissait penser que ce serait un frein dans une boucle).

  int bars_count=Bars;
  int handle=FileOpen("mydat.csv",FILE_CSV|FILE_WRITE);
  if(handle>0)
    {
     FileWrite(handle, "#","OPEN","CLOSE","HIGH","LOW");
     for(int i=0;i<bars_count;i++)
       FileWrite(handle, i+1,Open[i],Close[i],High[i], Low[i]);
     

FileFlush(handle);

     ...      for(int i=0;i<bars_count;i++)        FileWrite(handle, i+1,Open[i],Close[i],High[i], Low[i]);      FileClose(handle);     }

Ainsi, si je comprends bien la logique des développeurs, le fichier devrait être ouvert dans OnInit / Constructeur de la classe principale (peut-être pas seulement dans le constructeur) et fermé dans OnDeint / Destructif de la classe principale.

Danstous les autres cas, au lieu de FileClose, utilisez FileFlush (après FileWrite et après les boucles).


 

TheXpert:

Yedelkin:

J'ai interverti les lignes en suivant la documentation :

         FileFlush(handle_file);
         FileWrite(handle_file,t);

Où cela est-il écrit dans la documentation ?

Il existe une telle phrase dans la référence MQL5:

FileFlush

Note

La fonction FileFlush() doit être appelée entre les opérations de lecture d'un fichier et d'écriture dans un fichier.

Si "écrire dans un fichier" == fonction FileWrite(), alors lire : "La fonction FileFlush() doit être appelée avant la fonction FileWrite()". Ou avez-vous une opinion différente ?

LeXpert:

Yedelkin:
Mais je ne comprends toujours pas le sens de l'appel de FileFlush() avant FileWrite().

Comment pouvez-vous donner un sens à quelque chose qui n'en a pas ? Remettez l'ordre des lignes dans la page d'accueil et vérifiez-le à nouveau. Apparemment, la documentation ne l'a pas bien formulé.

Il est bon de savoir à l'avance ce qui a du sens et ce qui n'en a pas lorsqu'on étudie une nouvelle matière. Comme la nature ne nous a pas doté de tels talents, nous devons "prendre chaque nouvelle hauteur", tester, interpréter la documentation et les résultats. Je ne suis même pas sûr que les tests eux-mêmes soient écrits correctement. Au début, j'ai intuitivement placé FileFlush() après FileWrite(), mais après avoir relu le manuel, j'ai supprimé cet exemple.

LeXpert:

Intéressant:

OMG ! C'est absurde où se trouve la sortie. C'est ainsi que l'on entend des affirmations telles que "la POO est plus rapide" ou "les indicateurs sont lents, nous devrions mettre tout le code dans Expert Advisor".

Ce serait bien si chaque évaluation de "votre sortie est stupide" était suivie de l'explication de ce qui est stupide dans cette sortie :) Sinon, on ne sait pas dans quelle direction se diriger avec une telle sévérité de la part du pouvoir judiciaire :)

 
TheXpert:

Il ne sert à rien de faire disparaître les changements avant qu'ils n'apparaissent, car ils ne sont pas encore là :)

Vous ne le croirez pas, mais c'est exactement pour cette raison que j'ai écrit "Mais je ne comprends pas le sens d'appeler FileFlush() avant FileWrite()", en me référant à la documentation précédente. Mais je n'ai pas assez de courage et de connaissances pour remettre en question chaque ligne de la documentation :)
... Eh bien, la voie est libre - nous attendons ce que les développeurs diront si un problème est vraiment détecté.
 
Yedelkin:

Il existe une telle phrase dans la référence MQL5:

Si "write to file" == fonction FileWrite(), il lit : "La fonction FileFlush() doit être appelée avant la fonction FileWrite() ".Ou avez-vous une opinion différente ?

Analysons la description "plutôt malheureuse" et l'exemple de cette fonction pour MQL4.

void FileFlush( int handle)


Réinitialise sur le disque toutes les données restantes dans le tampon d'E/S du fichier.

Remarque : La fonction FileFlush() doit être appelée entre les opérations de lecture et d'écriture de fichiers.
Lorsque le fichier est fermé, les données sont automatiquement vidées sur le disque, il n'est donc pas nécessaire d'appeler FileFlush() avant d'appeler FileClose().

La ligne marquée ici est l'argument de la nécessité d'appeler FileFlush dans la boucle avant d'écrire dans le fichier.

Mais si nous comprenons cette phrase mot à mot, nous obtiendrons ce qui suit :

la fonction FileFlush() doit être appelée entre les opérations de lecture du fichier (la lecture est liée à FileReadXXX) et d'écriture dans le fichier (l'écriture est liée à FileWrite et FileWriteXXX).

Lors de la fermeture du fichier (lecture - lorsque FileClose est exécuté), les données sont vidées sur le disque automatiquement (lecture - lorsque FileFlush est exécuté automatiquement).


Je pense que les développeurs ne se sont pas beaucoup souciés de l'exactitude de la lecture de l'aide même dans la version MQL4 ; il est même ridicule de parler de mettre la partie tronquée dans MQL5.

À mon avis, la deuxième phrase du commentaire ci-dessus devrait au moins se présenter comme suit :

Les données sont automatiquement réinitialisées sur le disque lorsque le fichier estfermé, il n'est donc pas nécessaire d'appeler FileFlush() avant d'appeler FileClose().

C'est un peu désordonné aussi, mais d'un certain point de vue, cela explique pourquoi FileFlush ne doit pas être utilisé avant de fermer le fichier à l'aide de FileClose.


L'exemple n'est pas si simple, le texte parle d'une seule chose (utilisation entre les opérations de lecture et d'écriture), alors que l'exemple décrit l'utilisation entre deux opérations d'écriture en boucle (le travail à l'intérieur des boucles n'est d'ailleurs pas du tout pris en compte dans l'aide).

Ainsi, au minimum, les éléments suivants devraient être ajoutés :

1. une description de ce qu'est ce tampon d'entrée/sortie et de ce qui s'y passe réellement entre l'ouverture d'un fichier, la lecture d'un bloc de données, l'écriture d'un bloc de données et la fermeture du fichier.

Il s'agit très probablement de l'ensemble de la section sur les opérations sur les fichiers.

2. Donnez un exemple normalement compris (peut être basé sur une classe) de la façon d'utiliser correctement l'appel FileFlush pour l'accès à un fichier unique (par exemple, l'écriture de la valeur d'une minuterie).

3 Fournir un exemple normal d'appel lors du travail avec des tableaux. D'après ce que je comprends, l'exemple décrit dans la référence MQL4 fait référence au travail avec de grands tableaux, mais l'illustre de manière incorrecte (en un mot - pourquoi écrire deux fois une quantité assez importante de données identiques dans le fichier, si cela peut être fait plusieurs fois ?)

FileFlush - Документация на MQL4
  • docs.mql4.com
FileFlush - Документация на MQL4
 
Interesting:

La ligne mise en évidence ici est votre argument pour justifier la nécessité d'appeler FileFlush dans la boucle avant d'écrire dans le fichier.

Mais si nous comprenons ce commentaire mot à mot, nous obtenons ce qui suit :

la fonction FileFlush() doit être appelée entre les opérations de lecture du fichier (la lecture est liée à FileReadXXX) et d'écriture dans le fichier (l'écriture est liée à FileWrite et FileWriteXXX).

Lors de la fermeture du fichier (lecture - lors de l'exécution de FileClose), les données seront automatiquement vidées sur le disque (lecture - lors de l'exécution de FileFlush).

Je vois ce que vous voulez dire. Je suis désolé, car sans le savoir, j'ai assimilé l'opération "lire depuis le fichier" à la fonction FileOpen() (mon conseiller expert ne lira qu'à partir de OnInit(), tandis que pendant le traitement des ticks et des événements personnalisés - uniquement en écriture ; pour cette raison, je n'ai pas envisagé de fonctions comme FileReadXXX() dans la boucle). Néanmoins, FileFlush() avant FileWriteXXX() - le principe est le même dans les deux références. Et ce n'était pas une argumentation dans son sens classique (comme un raisonnement de ma position), mais simplement une réponse à la question pourquoi j'ai fait cette phrase.

Quoi qu'il en soit, si les développeurs ne répondent pas ici, je posterai une demande ce soir, avec un lien vers la discussion et les résultats intermédiaires. Il faut même deux demandes : 1) "bug - not a bug" et 2) changements dans la documentation. Voulez-vous faire la deuxième demande vous-même, puisque vous avez creusé si profondément le sujet ?

 
Yedelkin:

Je vois ce que je pense. J'avoue que, sans le savoir, j'ai assimilé l'opération "lire à partir d'un fichier" à la fonction FileOpen() (mon conseiller expert ne lira qu'à partir de OnInit(), tandis que pendant le traitement des ticks et des événements utilisateur - seulement en écriture ; pour cette raison, je n'ai pas envisagé de fonctions comme FileReadXXX() dans la boucle). Néanmoins, FileFlush() avant FileWriteXXX() - le principe est le même dans les deux références. Et ce n'était pas une argumentation dans son sens classique (comme un raisonnement de ma position), mais simplement la réponse à la question pourquoi j'ai fait cette phrase.

Quoi qu'il en soit, si les développeurs ne répondent pas ici, j'écrirai une demande ce soir, avec un lien vers la discussion et les résultats intermédiaires. Il faut même deux demandes : 1) "bug - not a bug" et 2) changements dans la documentation. Voulez-vous faire la deuxième demande vous-même, puisque vous avez creusé si profondément le sujet ?

1. Est-ce si profond ? Je serais probablement heureux de le faire, si je comprenais ce que les développeurs veulent dire et où.

Parfois, il est fait mention d'un tampon d'E/S, mais il n'y a pas de description précise de celui-ci. Ou est-ce que tout le monde ici sait ce qu'est le tampon d'E/S FILE ?

Est-il difficile d'ajouter une description normale de ce problème dans le chapitre sur les opérations sur les fichiers ? Ou de chercher dans le monde entier une réponse à ce que les développeurs avaient en tête ?

Je comprends que la taille de l'aide est limitée, mais pourquoi devrions-nous nous moquer de ceux qui commencent à apprendre le MQL ?

2. Pourquoi une mention de ce tampon que je n'ai trouvé que dans l'aide pour cette fonction, pourquoi il n'est pas mentionné ailleurs dans la section sur les opérations sur les fichiers ?

3. supposons que j'aie une idée de ce tampon d'entrée/sortie sous la forme approximative suivante

La notion de tampon d'entrée-sortie est liée au système de fichiers. Les données d'entrée et de sortie passent par ce tampon.

La mémoire tamponest une zone de la mémoire qui est allouée pour chaque fichier.

Lors de l'enregistrement dans un fichier, toutes les informations sont d'abord dirigées vers le tampon et s'y accumulent jusqu'à ce que tout le volume du tampon ne soit plus rempli. Ce n'est qu'après cela ou après la commande spéciale de dump (par exemple, FileClose ou FileFlush). les données sont transférées du tampon au fichier.

Lors de la lecture d'un fichier, les données sont d'abord lues dans le tampon, et la quantité de données lue n'est pas celle demandée, mais celle qui peut tenir dans le tampon.

Et les développeurs pensent-ils vraiment que toutes ces informations peuvent être intéressantes pour un nouveau venu étudiant MQL (si seulement cette définition peut être considérée comme valide pour ce langage) ?

Par exemple, je me demandais quelle est la taille de ce tampon et comment il est défini.

À mon avis, toutes ces informations, et pas seulement celles-ci, devraient se trouver dans la documentation du langage (là, et non dans divers articles et discussions sur le forum).

 
Interesting:
OK, je vais essayer d'écrire une référence moi-même.
 

Pourquoi le script ne renvoie-t-il pas la"date de dernière lecture" du fichier ?

int handle_file;
void OnStart()
  {
   handle_file=FileOpen("Ye_file2.bin",FILE_READ|FILE_WRITE|FILE_BIN);
   switch(handle_file)
     {
      case  INVALID_HANDLE: break;
      default:
         Print("Дата создания файла Ye_file2.bin: ",(datetime)FileGetInteger(handle_file,FILE_CREATE_DATE));
         for(int i=0;i<3;i++)
           {
            Sleep(3000);
            FileReadInteger(handle_file,CHAR_VALUE);
            Print("Дата последнего чтения Ye_file2.bin: ",(datetime)FileGetInteger(handle_file,FILE_ACCESS_DATE));
           }
         FileClose(handle_file);
     }
  }
 
Yedelkin:

Pourquoi le script ne renvoie-t-il pas la"date de dernière lecture" du fichier ?

Dernier accès, non lu. Rouvrez la poignée et vous serez heureux.
 
TheXpert:
Dernier accès, pas accès en lecture.

OK, comme vous l'avez peut-être remarqué, dans ma question, j'ai cité textuellement la phrase de la documentation :

ENUM_FILE_PROPERTY_INTEGER

Identifiant

Description de l'identifiant

FICHIER_EXISTANT

Contrôle d'existence

DATE DE CRÉATION DU FICHIER

Date de création

FICHIER_MODIFICATION_DATE

Date de la dernière modification

DATE D'ACCÈS AU FICHIER

Date de la dernière lecture

Question 1 : Pensez-vous qu'il y a une erreur de frappe dans la documentation, et qu'au lieu de "Date de dernière lecture", il faudrait dire "Date de dernière ouverture" ? Au moins d'après votre réponse, vous pouvez voir que les opérations "lire un fichier" et "accéder à un fichier" ont des significations différentes pour vous.

Plus loin. Si vous relancez plusieurs fois le script ci-joint, vous constaterez approximativement le même comportement :

FK      0       FileInteger (EURGBP,M1) 21:33:56        Дата создания файла Ye_file2.bin: 2011.09.03 21:22:25
IP      0       FileInteger (EURGBP,M1) 21:33:59        Дата последнего чтения Ye_file2.bin: 2011.09.03 21:33:57
RL      0       FileInteger (EURGBP,M1) 21:34:02        Дата последнего чтения Ye_file2.bin: 2011.09.03 21:33:57
NH      0       FileInteger (EURGBP,M1) 21:34:06        Дата последнего чтения Ye_file2.bin: 2011.09.03 21:33:57
MH      0       FileInteger (EURGBP,M1) 21:34:43        Дата создания файла Ye_file2.bin: 2011.09.03 21:22:25
EP      0       FileInteger (EURGBP,M1) 21:34:46        Дата последнего чтения Ye_file2.bin: 2011.09.03 21:34:06
 HL      0       FileInteger (EURGBP,M1) 21:34:50        Дата последнего чтения Ye_file2.bin: 2011.09.03 21:34:06
IH      0       FileInteger (EURGBP,M1) 21:34:53        Дата последнего чтения Ye_file2.bin: 2011.09.03 21:34:06

Ainsi, lors de la première exécution du script, le troisième appel àFileReadInteger() a lieu à21:34:06, mais la date de la dernière lecture/du dernier accès est différente :21:33:57.Cependant, la deuxième exécution du script (37 secondes plus tard) montre que le premier appel de la fonctionFileReadInteger() a donné 21 :34:06, c'est-à-dire l'heure du dernier appel de la fonctionFileReadInteger() lors de l'exécution du script précédent.

En outre, le deuxième lancement du script à 21:34:43 a lieu, ce qui signifie que la "réouverture d'une poignée", comme vous l'appelez, s'est produite au même moment. Mais après une telle "réouverture de poignée", on obtient21:34:06, c'est-à-dire un temps complètement différent de celui dont vous parlez.

Question 2 : comment faut-il interpréter cela ?

TheXpert:
Rouvrez la poignée et vous serez heureux.

Dans la situation actuelle, de bonnes nouvelles sont attendues lorsque les propriétés du fichier sont récupérées sans "réouverture" de la poignée.