IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 Delphi Discussion :

Lire un fichier seulement si celui-ci n'est pas déjà en cours de lecture/ecriture ?


Sujet :

Delphi

  1. #1
    Membre averti
    Homme Profil pro
    Paramétreur de progiciels
    Inscrit en
    Octobre 2006
    Messages
    970
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Paramétreur de progiciels

    Informations forums :
    Inscription : Octobre 2006
    Messages : 970
    Points : 381
    Points
    381
    Par défaut Lire un fichier seulement si celui-ci n'est pas déjà en cours de lecture/ecriture ?
    Bonjour,

    Je travaille avec deux applications Delphi et celles-ci communiquent entre elles via des fichiers.

    Je rencontre parfois un problème quand le premier programme est en train d'écrire dans un fichier, le second le lit alors que l'écriture de celui-ci n'est pas terminée puis le supprime.

    Je cherche une méthode me permettant de savoir si le fichier est utilisé actuellement (lecture/écriture) afin de l'ignorer pour le lire à la prochaine vérification.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     
    if FindFirst(ExtractFilePath(Application.ExeName) + 'Tickets\*.txt', faAnyFile, SR)=0 then
    begin
         repeat
              AssignFile(Fichier, ExtractFilePath(Application.ExeName) + 'Tickets\' + SR.FindData.cFileName);
              {$I-} Reset(Fichier); {$I+}
              if IOResult = 0 then
              begin
                   while not EOF(Fichier) do
                   begin
                        ReadLn(Fichier,Ligne);
                        IdTCPClient1.IOHandler.WriteLn(Ligne);
                        Log(Format('Envoi du ticket %s : %s',[SR.FindData.cFileName, Ligne]));
                   end;
                   CloseFile(Fichier);
                   DeleteFile(ExtractFilePath(Application.ExeName) + 'Tickets\' + SR.FindData.cFileName);
              end;
         until FindNext(SR) <> 0;
         FindClose(SR);
    end;
    Merci,
    ZiP

  2. #2
    Membre expérimenté
    Avatar de sat83
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2004
    Messages
    1 040
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mars 2004
    Messages : 1 040
    Points : 1 307
    Points
    1 307
    Par défaut
    Ouvrir le fichier en mode exclusif:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    var Handle : Integer ; 
    [...]
    // Tentative d'ouverture du fichier en mode exclusif
      Handle := FileOpen( f , fmShareExclusive ); 
     
     // Si le Handle est different de -1 le fichier est non-utilisé
     if (Handle <> -1) then                    
     begin
       FileClose(Handle) ;
       //Traitement;
     end;

  3. #3
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 763
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 763
    Points : 13 381
    Points
    13 381
    Par défaut
    Ca dépend du type d'information que tu envoies sur ton serveur, mais il faut faire très attention à ta gestion.

    Si la connexion tombe, seule une partie du fichier aura été envoyée. Si cela entraîne une exception, le début du fichier sera renvoyé une 2ème fois (Peut-être après redémarrage du programme puisque CloseFile n'a pas été appelé; pas de try..finally). S'il n'y a pas d'exception, le fichier sera effacé avant d'avoir été entièrement envoyé.

    Un autre cas si les noms de fichiers ne sont pas uniques (un numéro d'article par exemple) est que la 2ème application aura une chance (même infime) de réouvrir le fichier entre CloseFile et DeleteFile . Le début du fichier sera à nouveau envoyé une deuxième fois.

    Le plus sûr serait d'avoir une base de données, remplie par le client locale et vidée par le serveur locale au fur et à mesure de l'envoi .
    Au minimum, il faudrait pouvoir envoyer le fichier en une fois sans faire de lecture ligne par ligne.

  4. #4
    Membre averti
    Homme Profil pro
    Paramétreur de progiciels
    Inscrit en
    Octobre 2006
    Messages
    970
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Paramétreur de progiciels

    Informations forums :
    Inscription : Octobre 2006
    Messages : 970
    Points : 381
    Points
    381
    Par défaut
    Bonsoir,

    Je précise deux informations :
    - Le nom du fichier est unique
    - Celui-ci contient toujours une seule ligne dans laquelle sont les différentes informations

    En regardant sur Internet, je me suis rendu compte que j'avais peut-être mal placé mes directives, j'ai donc corrigé comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    {$I-}
    AssignFile(Fichier, ExtractFilePath(Application.ExeName) + 'Tickets\' + SR.FindData.cFileName);
    Reset(Fichier);
    {$I+}
    if IOResult = 0 then
    begin
    Cependant, le problème n'est pas réglé car j'ai une erreur : "Erreur E/S 32".

    Je vais modifier mon code afin d'essayer la méthode de sat83.

    Andnotor, je me réserve l'utilisation d'une base de données qu'en dernier recours si je ne trouve aucune solution correcte.

    Merci,
    ZiP

  5. #5
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 586
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 586
    Points : 25 262
    Points
    25 262
    Par défaut
    Tu n'as pas trouver mieux que des fichiers ?


    - Une Connexion TCP\IP ? tu pourrais avoir ainsi une gestion du ACK et NAK
    - Un FileMapping ? Plus délicat, c'est de la mémoire, faudrait un système de Sémaphore, cela fonctionne que si les deux programmes sont sur le même ordi
    - Un SendMessage WM_COPYDATA, tu peux envoyer un buffer, il sera recopié dans une zone mémoire libre d'utilisation par le receveur, le même ordi aussi, tu peux aussi gérer un ACK ou NAK


    Sinon, tu peux te protéger d'une manière très simple, tu créés un fichier .OK qui porte le même nombre que le fichier principal, tu n'essaye d'ouvrir que les fichiers ayant un .OK associé !

    C'est la méthode HPrim pour les transferts de Santé ét Laboratoire, qui a fait des preuves depuis 15 ans ! certe primitive mais efficace ! Des grandes sociétés comme Agfa utilise cela !

  6. #6
    Membre averti
    Homme Profil pro
    Paramétreur de progiciels
    Inscrit en
    Octobre 2006
    Messages
    970
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Paramétreur de progiciels

    Informations forums :
    Inscription : Octobre 2006
    Messages : 970
    Points : 381
    Points
    381
    Par défaut
    Bonsoir ShaiLeTroll,

    Je laisse tourner jusqu'à demain soir et en fonction des résultats du test je vais mettre en place la méthode HPrim.

    En fait, j'ai plusieurs clients sur des machines différentes qui sont connectés à un serveur. Les informations sont récupérées d'un programme propriétaire compilé via l'exécution d'un premier programme en ligne de commande qui me créé les fichiers "tickets". Le client qui est connecté en permanence au serveur analyse toutes les secondes la présence de nouveaux tickets et les transfèrent au serveur puis les suppriment.

    Merci pour votre aide,
    ZiP

  7. #7
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 586
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 586
    Points : 25 262
    Points
    25 262
    Par défaut
    Sinon, utilise un FindFirstNotifcation sur un Dossier, tant que le dossier change de taille, c'est qu'il est utilisé, ...
    tu mémorises la taille des fichiers, et si au bout de quelques secondes, il ne grossit plus, tu tente de l'ouvrir !
    J'ai utilise cette méthode pour un Client IRC (XChat, une très vieille version encore gratuite ), j'ai activé le log, et je surveille son dossier, je memorise la taille des ficheirs, et quand un fichier a changé de taille, j'affiche tout ce qui est entre l'ancienne taille et la nouvelle taille dans une bulle de notification de la barre des taches ... j'ai ainsi la conversation sans ouvrir le programme

    C'est ce que j'ai fait pour aspirer d'un logiciel d'un partenaire des fichiers, je lance son programme, je simule des clics (aucun moyen propre d'interagir et leur système automatique me posait le problème d'accès concurrentiel que je n'avais pas envie de gérer justement), puis tant que le dossier de travail change de taille, j'attends, je laisse un délai, et je ferme le programme, puis je peux tranquillement m'occuper des fichiers

  8. #8
    Membre averti
    Homme Profil pro
    Paramétreur de progiciels
    Inscrit en
    Octobre 2006
    Messages
    970
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Paramétreur de progiciels

    Informations forums :
    Inscription : Octobre 2006
    Messages : 970
    Points : 381
    Points
    381
    Par défaut
    Je ne connaissais pas cette fonction.

    Je vais me documenter.

    Merci,
    ZiP

Discussions similaires

  1. Lire un fichier Ascii ou texte, donnees en bloc pas en colonnes
    Par Fatehcz dans le forum Shell et commandes GNU
    Réponses: 9
    Dernier message: 27/03/2014, 13h14
  2. [Toutes versions] Lire un fichier texte dont l'encoding n'est pas connu
    Par jemore22 dans le forum Macros et VBA Excel
    Réponses: 4
    Dernier message: 13/01/2012, 09h28
  3. Créer un fichier texte si celui spécifié n'existe pas
    Par Roud9 dans le forum Entrée/Sortie
    Réponses: 14
    Dernier message: 25/03/2011, 09h31
  4. Réponses: 3
    Dernier message: 10/09/2009, 16h24
  5. Réponses: 10
    Dernier message: 15/01/2008, 12h03

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo