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

Langage Delphi Discussion :

Lecture et modification de gros fichier texte la plus rapide possible


Sujet :

Langage Delphi

  1. #41
    Rédacteur
    Avatar de Pedro
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    5 411
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 5 411
    Points : 8 078
    Points
    8 078
    Par défaut
    Citation Envoyé par TicTacToe
    juste un truc mais

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
      for i := -2048 to 2047 - 1 do
        FValues[i] := IntToStr(Trunc(256 * (i + 2048) / 4096));
    il y a pas le -1 (habituel) pour 2047
    pour 2047 ca te donnerait n'importe quel valeur
    Argh... L'aide au code... Merci TicTacToe
    Citation Envoyé par TicTacToe
    [Mode pinaille]
    sinon "(i+2048) shr 4" marche aussi mais c'est moins parlant.
    [/Mode pinaille]
    Bah, comme c'est un traitement hors processus, c'est pas bien grave

    PS: Zip (encore) mis à jour
    Pedro
    Aucune réponse aux sollicitations techniques par MP

    Faut pas attendre d'en avoir besoin pour s'en servir... (Lucien Stéphane)

    Les pages Source C'est bon. Mangez-en!
    Le défi Delphi
    Règles du forum - FAQ Delphi - Pensez au chtit
    Aéroclub Bastia Saint-Exupéry

  2. #42
    Membre régulier
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    75
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 75
    Points : 114
    Points
    114
    Par défaut
    Citation Envoyé par Paul TOTH Voir le message
    l'autre question importante est : est-ce que le temps de traitement est important ?

    l'avantage du REadLn/WriteLn c'est que c'est très simple à mettre en oeuvre, c'est très peu consommateur en mémoire et ça fonctionnera quelque soir la taille du fichier.

    tout charger dans un TStringList me parait la plus mauvaise solution, car le LoadFromFile place une copie du fichier en mémoire et l'affecte par SetTextStr() qui va faire un découpage de chaque ligne.

    il serait probablement intéressant de tester (encore une fois si le temps d'execution est important) en travaillent sur un buffer de taille "suffisante"

    en pseudo code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
     while RemplirBuffer=True do begin
      TrouverFinDeLigne;
      ExtraireDernierEntier;
      GenererNouvelleLigne;
      EcrireNouvelleLigne;
      DecalerBuffer;
     end;
    Perso c'est ce qui m'était "sauter" à l'esprit.

    Cepandant il va avoir beaucoup d'I/O. Alors je ne connais pas trop le Delphi pour les I/O, mais avoir un tableau statique de String qui contient quelque ligne et les ecrire par block ca gagnerais p'tet pas mal. Apres comme dit je sais pas comment est géré Writeln, si la primitive prends du temps, si elle est bien bufferisée, etc.

  3. #43
    Membre régulier
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    75
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 75
    Points : 114
    Points
    114
    Par défaut
    Citation Envoyé par Pedro Voir le message
    Argh... L'aide au code... Merci TicTacToe

    Bah, comme c'est un traitement hors processus, c'est pas bien grave

    PS: Zip (encore) mis à jour
    J'veut rien dire, mais pourquoi ne pas avoir :

    const MA_TABLE_DE_CONVERSION: array [-2048..2047] of Integer qui contivent directement la bonne valeur sans faire la boucle ?
    Bon okay c'est lourd à ecrire mais bon

  4. #44
    Membre expert
    Avatar de TicTacToe
    Inscrit en
    Septembre 2005
    Messages
    1 940
    Détails du profil
    Informations personnelles :
    Âge : 51

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 940
    Points : 3 575
    Points
    3 575
    Par défaut
    @TheMei: c'est vrai mais bon... comme le dis Pedro c'est une action initiale qui prends un temps infime et fixe comparé au temps de traitement alors bon

    Sinon Pedro, juste une petite chose pour encore grapiller,

    Si le format initial est vraiment bien figé, que le nombre de décimales est bien systématiquement 6 pour les composantes, et que la partie entiere des composantes ne dépassent jamais 999, il se trouve que le dernier espace ne peut pas être avant la position 27 de la chaine

    --> un seul PosEx( ' ', Chaine, 27) suffirait au lieu de 3.
    à voir si tu grapilles encore.
    Section Delphi
    La mine d'or: La FAQ, les Sources

    Un développement compliqué paraitra simple pour l'utilisateur, frustrant non ?
    Notre revanche ? l'inverse est aussi vrai ;-)

  5. #45
    Membre régulier
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    75
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 75
    Points : 114
    Points
    114
    Par défaut
    Oui le plus simple c'est de partir de la fin et de s'arreter au premier espace. Alors je sais pas si Delphi a des fonction pour...

  6. #46
    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
    Citation Envoyé par Pedro Voir le message
    Bon courage Tiens-moi au courant si tes recherches aboutissent
    PS: j'ai mis le ZIP à jour
    elles ont abouti, mais je ne joue pas dans la cour des grands!...

    Je suis parti sur une base de 3M lignes avec comme comparatif le dernier Zip de Tictactoe (je n'ai pas réussi à compiler je dernier de Pedro).
    methode1 (StringList): 6796 ms
    methode2 (textfiles) : 7062 ms
    methode3 (textfiles par blocs) : 3016 ms (sans les dernières optimisations )
    "l'autre (binaire) : 6156 ms (dont 60% = 3470 ms rien que pour les calculs...)



    Par contre sur les gros fichiers (44M lignes), les écarts se réduisent un peu, 136s pour 96s et, chez moi la methode 1 retourne un "out of memory".

    Je met mon code
    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
    55
    56
    57
    58
    59
    60
    61
    62
     
    procedure TForm1.Button1Click(Sender: TObject);
    var
      Fromfic, Tofic        : file of byte ;   // si > 2Go utiliser TFileStream
      NumRead, NumWritten   : Integer;
      Buf1: array[1..40960] of byte;   // taille à optimiser en fonction de
      Buf2: array[1..40960] of byte;   // celle du fichier à lire
      NbSpace       : integer;         // nombre d'espaces dans la ligne lue
      i, j, k       : integer  ;
      valeur        : string;
      TickDebut     : Cardinal;
     
    begin
      if OpenDialog1.Execute then begin
        AssignFile(Fromfic, OpenDialog1.FileName);
        Reset(FromFic);
     
        if SaveDialog1.Execute then begin
          AssignFile(ToFic, SaveDialog1.FileName);
          Rewrite(ToFic);
          TickDebut := GetTickCount;
          NbSpace := 0;    // après CRLF aussi  #13#10
          valeur := '';
          repeat
            BlockRead(FromFic, Buf1, SizeOf(Buf1), NumRead); // prévoir un talon
            i := 1;
            j := 0;  // nombre transférés
            for i := 1 to NumRead do begin
              if NbSpace < 3 then begin 
                inc(j);
                Buf2[j] := Buf1[i];
                if Buf1[i] = 32 then inc(NbSpace); // on copie tout jusqu'au 3eme espace
              end else begin  // if NbSpace < 3
                if Buf1[i] > 13 then valeur := valeur + chr(Buf1[i])  // # CRLF
                else begin
                  if Buf1[i] = 13 then begin    // CR
                    valeur := IntToStr((StrToInt(valeur)+ 2048) shr 4); // @Tictactoe
                    // (valeur + 2048) shr 4 semble 10 fois plus rapide que
                    // Trunc(256 * (Valeur + 2048) / 4096)
                    for k := 1 to length(valeur) do begin  // 1 à 5 caractères
                      inc(j);
                      Buf2[j] := ord(valeur[k]);
                    end;
                  end;
                  inc(j);
                  Buf2[j] := Buf1[i];
                  if Buf1[i] = 10 then begin    // LF réinit
                    NbSpace := 0;
                    valeur := '';
                  end;
                end; // else if Buf1[i] > 13
     
              end;  // else begin
            end;  // for i := 1 to NumRead
            BlockWrite(ToFic, Buf2, j, NumWritten);
          until (NumRead = 0);  // repeat
          CloseFile(FromFic);
          CloseFile(ToFic);
        end;  // if SaveDialog1.Execute
      end;  // if OpenDialog1.Execute
      Button1.Caption := IntToStr( GetTickCount - TickDebut ) + ' ms';
    end;
    bonne continuation
    à+

  7. #47
    Rédacteur
    Avatar de Pedro
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    5 411
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 5 411
    Points : 8 078
    Points
    8 078
    Par défaut
    Citation Envoyé par banban54 Voir le message
    bonjour
    Je suis parti sur une base de 3M lignes avec comme comparatif le dernier Zip de Tictactoe (je n'ai pas réussi à compiler je dernier de Pedro).
    Dis-moi ce qui ne va pas comme ça tout le monde pourra en profiter
    Citation Envoyé par TicTacToe
    Sinon Pedro, juste une petite chose pour encore grapiller,

    Si le format initial est vraiment bien figé, que le nombre de décimales est bien systématiquement 6 pour les composantes, et que la partie entiere des composantes ne dépassent jamais 999, il se trouve que le dernier espace ne peut pas être avant la position 27 de la chaine

    --> un seul PosEx( ' ', Chaine, 27) suffirait au lieu de 3.
    à voir si tu grapilles encore.
    Hélàs non, tu penses bien que j'y avais pensé Comme les points sont en coordonnée X, Y, Z et que l'origine est l'axe de l'appareil (en position centrale), il y a donc des valeurs négatives Donc je suis obligé de garder les 3 PosEx
    Par contre, peut-être en changeant le premier PosEx en Pos, on peut grapiller encore des millièmes (un test en moins)

    [Edit]
    Derniers tests:
    2 400 000 lignes => 4.3 secondes
    Avec 3 PosEx => 4.4 secondes

    PS: ZIP mis à jour
    Pedro
    Aucune réponse aux sollicitations techniques par MP

    Faut pas attendre d'en avoir besoin pour s'en servir... (Lucien Stéphane)

    Les pages Source C'est bon. Mangez-en!
    Le défi Delphi
    Règles du forum - FAQ Delphi - Pensez au chtit
    Aéroclub Bastia Saint-Exupéry

  8. #48
    Membre expert
    Avatar de TicTacToe
    Inscrit en
    Septembre 2005
    Messages
    1 940
    Détails du profil
    Informations personnelles :
    Âge : 51

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 940
    Points : 3 575
    Points
    3 575
    Par défaut
    Citation Envoyé par Pedro
    Hélàs non, tu penses bien que j'y avais pensé Comme les points sont en coordonnée X, Y, Z et que l'origine est l'axe de l'appareil (en position centrale), il y a donc des valeurs négatives Donc je suis obligé de garder les 3 PosEx
    Non non, je me suis mal exprimé, si la valeur absolu de tes composantes ne dépasse pas 999 (-999.123456 est donc autorisé), un seul PosEx suffit en position 27.

    Dans tous les cas on est sur qu'à cette position 27 on est avant le 3eme espace, mais on est sur aussi d'être après le 2eme...
    (un coup de bloc note pour s'en convaincre)

    Enfin bon
    Section Delphi
    La mine d'or: La FAQ, les Sources

    Un développement compliqué paraitra simple pour l'utilisateur, frustrant non ?
    Notre revanche ? l'inverse est aussi vrai ;-)

  9. #49
    Expert éminent sénior

    Avatar de sjrd
    Homme Profil pro
    Directeur de projet
    Inscrit en
    Juin 2004
    Messages
    4 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : Suisse

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2004
    Messages : 4 517
    Points : 10 152
    Points
    10 152
    Par défaut
    Citation Envoyé par themei Voir le message
    Oui le plus simple c'est de partir de la fin et de s'arreter au premier espace. Alors je sais pas si Delphi a des fonction pour...
    Je pense aussi. Il existe bien LastDelimiter, mais cette fonction part du début car elle supporte les MBCS.

    En voici une qui part vraiment du bout :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    function RightPos(C: Char; const Str: string): Integer;
    begin
      Result := Length(Str);
      while Result > 0 do
      begin
        if Str[Result] = C then
          Exit;
        Dec(Result);
      end;
    end;
    Renvoie 0 si non trouvé.

    Pas la peine d'en faire une version ASM, on peut pas faire mieux que ce code compilé Vive le compilo Delphi

    Edit : oui bon en fait y'a moyen de faire un peu mieux :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    function RightPos(C: Char; const Str: string): Integer;
    asm
            MOV     CL,AL
            MOV     EAX,EDX
            TEST    EAX,EAX
            JZ      @@exit
            MOV     EAX,[EAX-4]
    @@loop:
            CMP     CL,[EDX+EAX-1]
            JE      @@exit
            DEC     EAX
            JNZ     @@loop
    @@exit:
    end;
    (code testé)
    sjrd, ancien rédacteur/modérateur Delphi.
    Auteur de Scala.js, le compilateur de Scala vers JavaScript, et directeur technique du Scala Center à l'EPFL.
    Découvrez Mes tutoriels.

  10. #50
    Rédacteur
    Avatar de Pedro
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    5 411
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 5 411
    Points : 8 078
    Points
    8 078
    Par défaut
    Citation Envoyé par TicTacToe Voir le message
    Non non, je me suis mal exprimé, si la valeur absolu de tes composantes ne dépasse pas 999 (-999.123456 est donc autorisé), un seul PosEx suffit en position 27.
    Ah Ok j'ai compris
    Je vais essayer ça
    Citation Envoyé par sjrd
    Edit : oui bon en fait y'a moyen de faire un peu mieux :
    Je vais aussi essayer ça
    Résultats dans quelques minutes...
    Pedro
    Aucune réponse aux sollicitations techniques par MP

    Faut pas attendre d'en avoir besoin pour s'en servir... (Lucien Stéphane)

    Les pages Source C'est bon. Mangez-en!
    Le défi Delphi
    Règles du forum - FAQ Delphi - Pensez au chtit
    Aéroclub Bastia Saint-Exupéry

  11. #51
    Rédacteur
    Avatar de Pedro
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    5 411
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 5 411
    Points : 8 078
    Points
    8 078
    Par défaut
    Résultats pour 2 405 002 lignes très exactement:
    Optimisation TicTacToe: 4 secondes pile
    Optimisation sjrd: A peine plus (entre 1 et 3 centièmes)

    Citation Envoyé par sjrd
    Pas la peine d'en faire une version ASM, on peut pas faire mieux que ce code compilé Vive le compilo Delphi
    +1000

    Je vous dis: ça va être instantané!
    Pedro
    Aucune réponse aux sollicitations techniques par MP

    Faut pas attendre d'en avoir besoin pour s'en servir... (Lucien Stéphane)

    Les pages Source C'est bon. Mangez-en!
    Le défi Delphi
    Règles du forum - FAQ Delphi - Pensez au chtit
    Aéroclub Bastia Saint-Exupéry

+ Répondre à la discussion
Cette discussion est résolue.
Page 3 sur 3 PremièrePremière 123

Discussions similaires

  1. lecture de (très) gros fichiers texte
    Par Paul18 dans le forum Scilab
    Réponses: 7
    Dernier message: 14/06/2011, 22h05
  2. Problème lecture gros fichier texte
    Par UnnamedBoy dans le forum Entrée/Sortie
    Réponses: 7
    Dernier message: 22/02/2008, 11h13
  3. [VBA-E] Ecrire un fichier texte le plus rapidement possible
    Par spileo dans le forum Macros et VBA Excel
    Réponses: 5
    Dernier message: 13/09/2007, 20h51
  4. [C#]Lecture gros fichier texte
    Par kekesilo dans le forum Windows Forms
    Réponses: 5
    Dernier message: 20/05/2006, 13h58
  5. [VBA-E]Telecharger un gros fichier texte
    Par Elstak dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 10/04/2006, 09h16

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