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 :

Comment lire la dernière ligne d'un fichier text.


Sujet :

Delphi

  1. #1
    Membre régulier
    Inscrit en
    Novembre 2006
    Messages
    321
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 321
    Points : 88
    Points
    88
    Par défaut Comment lire la dernière ligne d'un fichier text.
    Bonjours,
    Est-il possible de lire directement la dernière ligne d'un fichier texte.

    Normalement on lit une ligne du fichier par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
     Readln(F,Stg);  // Jusqu'au prochain saut de ligne
    Pour lire toutes les lignes on fait une boucle jusque EOF.

    Mon problème est que si j'ai 10000 lignes sa prend un certain temps..,de la première ligne jusque à la dernière ligne ainsi j'aimerais
    bien accéder directement à cette dernière ligne. Y a t-il une solution ou une autre possibilité d'accéder à cette dernière ligne.
    Merci beaucoup pour me guider.
    Salutations
    Ardely

  2. #2
    Expert confirmé
    Homme Profil pro
    Inscrit en
    Septembre 2006
    Messages
    2 952
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2006
    Messages : 2 952
    Points : 4 378
    Points
    4 378
    Par défaut
    Citation Envoyé par Ardely
    Bonjours,
    Est-il possible de lire directement la dernière ligne d'un fichier texte.

    Normalement on lit une ligne du fichier par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
     Readln(F,Stg);  // Jusqu'au prochain saut de ligne
    Pour lire toutes les lignes on fait une boucle jusque EOF.

    Mon problème est que si j'ai 10000 lignes sa prend un certain temps..,de la première ligne jusque à la dernière ligne ainsi j'aimerais
    bien accéder directement à cette dernière ligne. Y a t-il une solution ou une autre possibilité d'accéder à cette dernière ligne.
    Merci beaucoup pour me guider.
    Salutations
    Ardely

    exemple ici
    (une implémentation de la commande "tail")

  3. #3
    Membre régulier
    Inscrit en
    Novembre 2006
    Messages
    321
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 321
    Points : 88
    Points
    88
    Par défaut
    Je pense le plus simple c'est de prendre les fonctions
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    FilePos() // ce positioner dans le fichier
    et en suite de lire avec
    Si quelqu'un à une autre solutions à me proposer...
    Grand merci pour l'aide!
    Salutations

  4. #4
    Membre averti
    Inscrit en
    Octobre 2005
    Messages
    338
    Détails du profil
    Informations forums :
    Inscription : Octobre 2005
    Messages : 338
    Points : 383
    Points
    383
    Par défaut
    bonjour
    je ne pense pas que ce soit la bonne solution!
    Filepos et Blockread ne s'appliquent pas au fichiers textes

    aide delphi
    Pour utiliser FilePos, le fichier doit être ouvert et il ne doit pas s'agir d'un fichier texte.
    à plus!

  5. #5
    Expert confirmé
    Avatar de Sub0
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2002
    Messages
    3 573
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Décembre 2002
    Messages : 3 573
    Points : 4 219
    Points
    4 219
    Par défaut
    Utilise une TStringList plutôt :
    http://www.developpez.net/forums/sho...88#post1648888

    Ainsi, pour récupérer la dernière ligne d'un fichier texte :
    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
    Function GetLastRow(FileName: String): String;
    Var f: TStringList;
    Begin
      Result := '';
      f := TStringList.Create;
      Try
        f.LoadFromFile(FileName);
        If (f.Strings.Count > 0) Then 
            Result := f.Strings[f.Strings.Count - 1]
        Else
          ShowMessage('Le fichier est vide!');
      Except
        ShowMessage('Erreur durant l''ouverture du fichier!'); 
      End;
      f.Free;
    End;

  6. #6
    Membre expert
    Avatar de LadyWasky
    Femme Profil pro
    Inscrit en
    Juin 2004
    Messages
    2 932
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 54
    Localisation : France, Hauts de Seine (Île de France)

    Informations forums :
    Inscription : Juin 2004
    Messages : 2 932
    Points : 3 565
    Points
    3 565
    Par défaut
    Et avec l'utilisation d'un TStringList, ne serait-ce-t'il pas plus simple ?

    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
    var UnStringList:TStringList;
                   DerniereLigne:string;
    begin
      //Création du STringList
      UnStringList:=TStringList.Create; 
      try
         //Chargement du fichier texte
         UnStringList.LoadFromFile('MonFichier.txt');
         //Récupération de la dernière ligne
         DerniereLigne:=UnStringList.strings[UnStringList.Count-1];
      finally
         //Destruction du StringList
         UnStringList.Free;
      end;
     
     
      //Affichage;
      ShowMessage(DerniereLigne);
    end;
    Grilled par Sub0

  7. #7
    Expert éminent
    Avatar de qi130
    Homme Profil pro
    Expert Processus IT
    Inscrit en
    Mars 2003
    Messages
    3 911
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France

    Informations professionnelles :
    Activité : Expert Processus IT
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2003
    Messages : 3 911
    Points : 6 032
    Points
    6 032
    Par défaut
    Cependant, même si le chargement du StringList est optimisé, il oblige de lire tout le fichier...et c'est ce que Ardely cherche à éviter.

    Citation Envoyé par banban54
    bonjour
    je ne pense pas que ce soit la bonne solution!
    Filepos et Blockread ne s'appliquent pas au fichiers textes
    Oui s'ils sont déclarés en tant que tels (TextFile).

    Pour autant, un fichier texte est comme tout fichier: une suite d'octets, et rien n'interdit a priori de le lire octet par octet. Bien sûr, la gestion du CRLF est à inclure, si l'on veut en tenir compte.

  8. #8
    Membre expert
    Avatar de LadyWasky
    Femme Profil pro
    Inscrit en
    Juin 2004
    Messages
    2 932
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 54
    Localisation : France, Hauts de Seine (Île de France)

    Informations forums :
    Inscription : Juin 2004
    Messages : 2 932
    Points : 3 565
    Points
    3 565
    Par défaut
    Et la fonction Seek(), elle fonctionne avec les fichiers textes ? Je ne sais plus, il me semble que oui.
    Edit : ou plutot non... Je ne sais plus, grosse fatigue

  9. #9
    Membre averti
    Inscrit en
    Octobre 2005
    Messages
    338
    Détails du profil
    Informations forums :
    Inscription : Octobre 2005
    Messages : 338
    Points : 383
    Points
    383
    Par défaut
    qi130

    je ne suis pas sûr que Ardely aime s'amuser avec du binaire sur des fichiers textes de plus 10000 lignes, sinon il aurait structuré ses données autrement!
    du genre:
    LongeurDeLaDonnées(en binaire) suivi du binaire correspondant à la ligne de texte

    et même pour aller à la dernière information il faut quand même lite tous le fichier dans ce cas!

  10. #10
    Expert éminent
    Avatar de qi130
    Homme Profil pro
    Expert Processus IT
    Inscrit en
    Mars 2003
    Messages
    3 911
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France

    Informations professionnelles :
    Activité : Expert Processus IT
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2003
    Messages : 3 911
    Points : 6 032
    Points
    6 032
    Par défaut
    Citation Envoyé par banban54
    qi130

    je ne suis pas sûr que Ardely aime s'amuser avec du binaire sur des fichiers textes de plus 10000 lignes, sinon il aurait structuré ses données autrement!
    Certes, encore faut-il avoir cette possibilité , hélas, la programmation ne fait pas toujours suite à une phase de conception académique.

    Citation Envoyé par Aide Delphi
    l'instruction Seek(F, FileSize(F)) déplace la position du curseur en fin de fichier.
    Ensuite, il suffit de remonter (FileSize(F)-n) jusqu'à l'avant dernier CRLF (ou plutôt LFCR puisqu'on lit à l'envers).

    Enfin, ce n'est qu'une idée.

  11. #11
    Membre éprouvé

    Profil pro
    Inscrit en
    Mai 2003
    Messages
    582
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Mai 2003
    Messages : 582
    Points : 915
    Points
    915
    Par défaut
    Je propose la lecture d'un bloc a la fin du fichier
    c'est rapide est cela devrait couvrire beaucoup de cas...

    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
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
     
    //==============================================================================
    //== Obtient la derniere Ligne d'un fichier texte.
    //== la derniere ligne doit être plus petite que 1022 caractères
    function GetLastLn(TextFileName:string):string;
    const
        BUFF_SIZE=1024;
        CRLF= #13+#10;
    var
        size : dword;
        BigBuffer:array [0..BUFF_SIZE] of char;
        f: file of char;
        LastPosCRLF:integer;
        SizeRead:Cardinal;
        TempStr:string;
    begin
        FillChar(BigBuffer,BUFF_SIZE,#0);
        AssignFile(f, TextFileName);
        try
            Reset(f);
            size := FileSize(f);
            if size>BUFF_SIZE then Seek(f,size-BUFF_SIZE);
            BlockRead(  f,BigBuffer,BUFF_SIZE,SizeRead);
            TempStr:=BigBuffer;
            LastPosCRLF:=LastDelimiter(CRLF,TempStr);
            if LastPosCRLF<>0 then
                result:=Copy(TempStr,LastPosCRLF+1,Length(TempStr)-LastPosCRLF)
            else
                result:='';
        finally
            CloseFile(f);
        end;
    end;
    je crois que c'est ce que notre ami Ardely voulait...

    EDITION!
    result:=Copy(TempStr,LastPosCRLF+1,BUFF_SIZE-LastPosCRLF)
    change pour
    result:=Copy(TempStr,LastPosCRLF+1,Length(TempStr)-LastPosCRLF)

  12. #12
    Membre régulier
    Inscrit en
    Novembre 2006
    Messages
    321
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 321
    Points : 88
    Points
    88
    Par défaut
    Hallo, a tous
    C'est super de voir les posibilités qu'on me propose (Merci), effectivement
    je pense ce que "Eric Boisvert" me propose est bien ce que je cherche..
    Je vais testé et vous dire plus tard comment sa c'est passer...

  13. #13
    Membre émérite Avatar de edam
    Homme Profil pro
    Développeur Delphi/c++/Omnis
    Inscrit en
    Décembre 2003
    Messages
    1 894
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Maroc

    Informations professionnelles :
    Activité : Développeur Delphi/c++/Omnis
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 894
    Points : 2 770
    Points
    2 770
    Par défaut
    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
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
     
    procedure TForm1.LastText;
    var
        f:file of byte;
        s,m:string;
        t,j:integer;
        b,bb:Boolean;
    Function Dechiffre:Boolean;
    var
        i,j:integer;
        n:string;
    begin
         n:=m;
         j:=length(m);
         i:=j;
         while (j>0) and (n[j]<>#10) do dec(j);
         result:=(j>0);
         if result then
           begin
             i:=i-j;
             setlength(m,i);
             inc(j);
             move(n[j],m[1],i);
           end;
    end;
    begin
         if not OpenDialog1.Execute then exit;
         assignfile(f,OpenDialog1.FileName);
         {$i-}
         reset(f);
         if IOResult<>0 then exit;
         t:=filesize(f);
         s:='';
         b:=false;bb:=false;
         repeat
           t:=t-$400;
           if t<0 then t:=0;
           seek(f,t);
           setlength(m,$400);
           BlockRead(f,m[1],$400,j);
           if not bb then
             begin
                while (j>0) and ((m[j]=#10) or (m[j]=#13)) do dec(j);
                bb:=j>0;
             end;
           if bb then
             begin
               if j<$400 then setlength(m,j);
               b:=Dechiffre;
               s:=m+s;
             end;
         until (b) or (t=0);
         ShowMessage(s);
    end;

  14. #14
    Expert confirmé
    Avatar de Sub0
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2002
    Messages
    3 573
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Décembre 2002
    Messages : 3 573
    Points : 4 219
    Points
    4 219
    Par défaut
    Tu peux également essayer avec TFileStream. Peut-être quelque chose comme ça :
    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
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    Function GetLastRow(fn: String): String;
    Var
      f: TFileStream;
      o: Integer;
      st: String;
    Begin
      Result := '';
      Try
        f := TFileStream.Create(fn, fmOpenRead);
        o := f.Size - 1;
        st := #0;
        Repeat
          If (o >= 0) Then Begin
            f.Seek(o, soFromBeginning);
            f.Read(st[1], 1);
            Result := st + Result;
            o := o - 1;
          End;
        Until (o <= 0) Or ((st = #13) And (Trim(Result) <> ''));
      Except
      End;
      FreeAndNil(f);
    End;
     
     
    Procedure TForm1.Button1Click(Sender: TObject);
    Begin
      If (OpenDialog1.Execute) Then
        ShowMessage(GetLastRow(OpenDialog1.FileName));
    End;
    Maintenant, si tu cherches le code le plus rapide, il faudra tester en chronomètrant le traitrement d'une serie de fichiers avec les différentes solutions proposées dans ce sujet. Une fois que tu l'auras trouvé, tu pourras toujours l'optimiser et le coder en assembleur... à+

  15. #15
    Membre régulier
    Inscrit en
    Novembre 2006
    Messages
    321
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 321
    Points : 88
    Points
    88
    Par défaut
    Bonjours
    Je me suis penché sur la solution de 'Eric Boisvert' en cherchant je constate que
    LastPosCRLF est toujours égale à size!!
    Je suis en train de cherche le pourquoi!!!
    Salutations

  16. #16
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Février 2004
    Messages
    48
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2004
    Messages : 48
    Points : 30
    Points
    30
    Par défaut
    Bonjour, je suis interessé par ces solutions que vous donnez ... pourrais tu, Auderly, s'il te plait nous donner le resultat de tes tests de vitesse sur les differentes propositions? je suis sûr que ce problème est recurant et ça interesserait beacoup de personnes de savoir quel est l'algorithme gagnant ... merci

  17. #17
    Membre émérite Avatar de edam
    Homme Profil pro
    Développeur Delphi/c++/Omnis
    Inscrit en
    Décembre 2003
    Messages
    1 894
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Maroc

    Informations professionnelles :
    Activité : Développeur Delphi/c++/Omnis
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 894
    Points : 2 770
    Points
    2 770
    Par défaut
    Citation Envoyé par Ardely
    Bonjours
    Je me suis penché sur la solution de 'Eric Boisvert' en cherche je constate que
    LastPosCRLF est toujours égale à size!!
    Je suis en train de cherche le pourquoi!!!
    Salutations
    si tu regarde mon code il elémine le #13#10 de fin de fichier (si elle est trouvé)

  18. #18
    Membre régulier
    Inscrit en
    Novembre 2006
    Messages
    321
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 321
    Points : 88
    Points
    88
    Par défaut
    En faite pourquoi j'avais (LastPosCRLF = size) parce-que j'avais un 13 10 en fin de ligne... Problem résolu et qui fonctionne trés bien
    J'ai aussi testé la posibilité de "Sub0" qui fonctionne aussi trés bien.
    Dabort un grand merci pour que vous m'avez bien éluminer sans faute!
    Je dois encore faire quelques tests et puis je vous mettrais le résultat des performances.
    Salutations
    Ardely

  19. #19
    Membre éprouvé

    Profil pro
    Inscrit en
    Mai 2003
    Messages
    582
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Mai 2003
    Messages : 582
    Points : 915
    Points
    915
    Par défaut
    Voilà ici une mise à jours...
    l'autre version du code donnait problème avec des fichiers
    avec 1 seule ligne...donc sans CRLF à la fin!

    j'ai ajouter l'option pour ignorer la dernière ligne si elle est vide
    (un fichier qui ce termine par CRLF)
    par défaut à FALSE car selon moi, si la dernière ligne est vide
    c'est peut-être voulu et on veut peut-être le savoir...
    donc voilà ce que ca donne.

    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
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
     
    //==============================================================================
    //== Obtient la derniere Ligne d'un fichier texte.
    //== la derniere ligne doit être plus petite que 1022 caractères
    //== Option: SkipLastEmptyLine=TRUE
    //==         Retourne alors l'avant dernière ligne si le fichier termine
    //==         par un CRLF
    //== Une erreur : "I/0 error 103" arrive si le fichier n'existe pas.
    //== La fonction appelante doit donc faire la vérification de l'existance
    //== des fichiers.
    function GetLastLn(TextFileName:string;SkipLastEmptyLine:boolean=FALSE):string;
    const
        BUFF_SIZE=1024;
        CRLF= #13+#10;
    var
        size : dword;
        BigBuffer:array [0..BUFF_SIZE] of char;
        f: file of char;
        LastPosCRLF:integer;
        SizeRead:Cardinal;
        TempStr:string;
    begin
        FillChar(BigBuffer,BUFF_SIZE,#0);
        AssignFile(f, TextFileName);
        try
            Reset(f);
            size := FileSize(f);
            if size<>0 then
            begin
                if size>BUFF_SIZE then Seek(f,size-BUFF_SIZE);
                BlockRead(  f,BigBuffer,BUFF_SIZE,SizeRead);
                TempStr:=BigBuffer;
                if (SkipLastEmptyLine=TRUE) and (strcomp(@TempStr[SizeRead-1],CRLF)=0) then
                    TempStr:=Copy(TempStr,1,SizeRead-2); // Remove last CRLF
                LastPosCRLF:=LastDelimiter(CRLF,TempStr);
                if LastPosCRLF<>0 then
                    result:=Copy(TempStr,LastPosCRLF+1,Length(TempStr)-LastPosCRLF)
                else
                    result:=TempStr;
            end
            else
                result:='';
        finally
            CloseFile(f);
        end;
    end;

  20. #20
    Membre régulier
    Inscrit en
    Novembre 2006
    Messages
    321
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 321
    Points : 88
    Points
    88
    Par défaut
    Bonsoir.
    J'ai finis mes tests et je conclut que les codes proposés par 'Eric Boisvert' et 'Sub0' sont très très rapide (C'est aussi normal on attaque directement la fin de la ligne) j'ai testé avec un fichier de 11MB.
    Le seul problème est que si à la fin de la ligne il existe des autres caractères ASCI
    1 à 128 expl. code 26 fin de page le code de 'Eric Boisvert' n'affiche erreur ou rien je pense que c'est du au format:
    En tout cas pour moi, j'ai bien appris et j'ai bien pu avancer avec vôtre aide, Merci beaucoup pour les propositions.
    Salutations

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Lire les 20 dernières lignes d'un fichier texte
    Par David_24 dans le forum Tcl/Tk
    Réponses: 1
    Dernier message: 25/05/2009, 17h47
  2. Réponses: 1
    Dernier message: 27/04/2009, 19h04
  3. Lire une les 3 dernières ligne d'1 fichier texte
    Par BECHE dans le forum Langage
    Réponses: 2
    Dernier message: 08/02/2009, 14h38
  4. Réponses: 6
    Dernier message: 22/09/2008, 14h52
  5. Comment lire une seul ligne d'un fichier texte?
    Par Julien1987 dans le forum Windows Forms
    Réponses: 3
    Dernier message: 18/01/2007, 13h36

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