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 :

[D2009] TFileStream Big Files (demande de conseil)


Sujet :

Delphi

  1. #81
    Membre éprouvé Avatar de BuzzLeclaire
    Homme Profil pro
    Dev/For/Vte/Ass
    Inscrit en
    Août 2008
    Messages
    1 606
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Dev/For/Vte/Ass

    Informations forums :
    Inscription : Août 2008
    Messages : 1 606
    Points : 1 113
    Points
    1 113
    Par défaut
    Citation Envoyé par Gilbert Geyer Voir le message
    Aujourd'hui : Au pire j'utiliserai la propriété dupignore des stringlists et puis c'est tout.
    Hier : ... car quaziement aucun doublon.
    Tu te trompe...
    - le hier : c'etait sur le Numéro de Facture NumFact (quaziement impossible d'avoir un doublon la dessus)
    - le Aujourd'hui : je parlais des numéros de compte !!! c'est totalement différent.... là tu as toujours des doublons...


    En final l'idéal serait d'utiliser FView d'une façon ou d'une autre pour repérer et récupérer dans la StringList uniquement les Numéros des lignes dont le Numéro de Compte (ou le Numéro de Facture ?) n'apparait qu'une seule et unique fois dans le fichier-source pour pouvoir ignorer les doublons. Et comme les lectures avec FViev sont très rapides rien n'empêche de faire ça avec des boucles imbriquées avec contenant un :
    Un Fview sur plusieurs fichiers sa ce complique, actuellement je charge 2 fichiers de 117Mo et le traitement est raisonnable en utilisant le dupignore.
    (cela représentent 4 000 000 de lignes)

    Bye.

  2. #82
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 266
    Points
    3 266
    Par défaut
    Re-bonjour,

    OK, vu. De toutes façons on est très loin des 8 heures que citais dans ton premier post.

    A+.

  3. #83
    Membre éprouvé
    Avatar de Montor
    Homme Profil pro
    Autre
    Inscrit en
    Avril 2008
    Messages
    879
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Autre

    Informations forums :
    Inscription : Avril 2008
    Messages : 879
    Points : 963
    Points
    963
    Par défaut
    cette fonction pour creer un fichier test
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    var
     i,H:integer;
     S:string;
    begin        
       H:= FileCreate('D:\test.txt');
       for i:= 0 to 800000 do
       begin
         S:=Inttohex(i,8);
         FileWrite(H,Pchar(S)^,8);
       end;
    end;
    Voici ma derniere version pour recuperer les noms sur la liste StringHash
    unité tu.pas
    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
    unit tu;
     
    interface
    uses inifiles;
    type
      TDerivedList=class(TStringHash)
      private
        FSize  :Integer;
        FData  :PPHashItem;
      public
        constructor Create(Size: Cardinal);
        function Add(const AKey: string):PHashItem;
      end;
     
    implementation
     
    constructor TDerivedList.Create(Size: Cardinal);
    begin
      inherited Create(Size);
      inherited Add(#0,0);
      FData := Find(#0);
      Remove(#0);
      FSize := Size;
    end;
     
    function TDerivedList.Add(const AKey: string):PHashItem;
    var
      H   : Integer;
      P   : PPHashItem;
    begin
      P:=FData;
      H := HashOf(AKey) mod Cardinal(FSize);
      New(Result);
      inc(P,H);
      with Result^ do
      begin
       Key    := AKey;
       Value  := 0;
       Next   := P^;
      end;
      P^:= Result;
    end;
     
    end.
    N(oublier pas d'ajouter
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    uses FView,tu,inifiles;
    pour l'utilisation
    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
    procedure Lire();
    var
       ptr  : PFileStruct;
       N    : integer;
       G    : cardinal;
       Bin  : pointer;
       FV   : TFileView;
       Count: integer;
       ListNoms   : TList;
       L    : TDerivedList;
    begin
      G := GetTickCount;
      L  := TDerivedList.Create($8000);
      FV := TFileView.Create('D:\test.txt');
      ListNoms  := TList.Create;
      try
        if FV.Loaded then
        begin
          Count := FV.FileSize div SizeOfFileStruc;
          Ptr   := FV.View;
          for N := 0 to Count-1 do
           begin
            if L.ValueOf(Ptr^.NumFact.NumFact) = -1 then
              ListNoms.Add(L.Add(Ptr^.NumFact.NumFact));
     
            inc(ptr);
           end;
        end;
     
       Showmessagefmt('%.d',[GetTickCount - G]);
     
       {Affichage}
       for N := 0 to ListNoms.Count-1 do
         Showmessagefmt('%s',[THashItem(ListNoms[N]^).Key]);
     
      finally
        FV.Free;
        L.Free;
        ListNoms.Free;
      end;
    end;

  4. #84
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 266
    Points
    3 266
    Par défaut Pour ignorer les doublons avec FView
    Re-bonjour,

    J'ai testé mon idée évoquée dans mon post de 11h02 pour la création de la liste des N° de lignes qui ne sont pas des doublons avec ce code sans TStringHash indisponible sous D5 :
    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
    procedure TForm1.bIgnorerDoubolnsDeFViewClick(Sender: TObject); 
    var       ptr0,ptr1 : PFileStruc;
              N0,N1,C,Count : integer; SL : tStringList;
              G   : cardinal;
              FV : TFileView; fiSource : string; NomCompare : String; Doublon : boolean;
    begin     G := GetTickCount;
              C := 0;
              fiSource:=ExtractFilePath(Application.ExeName)+'Test100Mo.txt';
              FV := TFileView.Create(fiSource);
              try
                if FV.Loaded then
                begin
                  SL := tStringList.create;
                  Count := FV.FileSize div SizeOfFileStruc;
                  Ptr0  := FV.View;
                  for N0 := 0 to Count-2 do
                  begin NomCompare:=Ptr0^.Nom; Doublon:=False;
                        for N1:=N0+1 to Count do
                        begin Ptr1 := FV.View; inc(Ptr1,N1);
                              if Ptr1^.Nom = NomCompare
                              then begin Doublon:=True; Break; end // un doublon
                              else inc(Ptr1);
                        end;
                        if not Doublon then SL.add(intToStr(N0));
                        inc(Ptr0);
                  end;
                end;
              finally
                FV.Free;
              end;
     
              G := GetTickCount - G;
              RichEdit2.lines.add('Fichier-source : '+fiSource);
              RichEdit2.lines.add(format('Liste sans doublons crée avec FView en %d ms : conservé %d lignes sur %d lignes',[G, SL.Count, Count]));
              //RichEdit2.lines.addStrings(SL);
    end;
    Résultat du test :
    Fichier-source : D:\D_Fichiers\Test100Mo.txt
    Liste sans doublons crée avec FView en 2593 ms : conservé 6 lignes sur 845628 lignes
    Moins de 3 secondes pour des boucles imbriquées sur un Fichier de 100 Mo contenant 99,999 % de doublons c'est pas mal. (Pentium III à 1,13 GHz)

    Suffit, en cas de besoin, de remplacer dans le code le if Ptr1^.Nom = NomCompare par le If Ptr^.NumCompte = NumCompteCompare pour l'adapter au cas des factures.

    A+.

  5. #85
    Membre éprouvé
    Avatar de Montor
    Homme Profil pro
    Autre
    Inscrit en
    Avril 2008
    Messages
    879
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Autre

    Informations forums :
    Inscription : Avril 2008
    Messages : 879
    Points : 963
    Points
    963
    Par défaut
    Moins de 3 secondes pour des boucles imbriquées sur un Fichier de 100 Mo contenant 99,999 % de doublons c'est pas mal. (Pentium III à 1,13 GHz)

    Suffit, en cas de besoin, de remplacer dans le code le if Ptr1^.Nom = NomCompare par le If Ptr^.NumCompte = NumCompteCompare pour l'adapter au cas des factures.
    non non et non le hic est lorsque il n y pas de doublons essaie de créer un fichier de test la fonction que jai posté
    TStringHash
    c est un class de quelque lignes tu peux le trouve sur le net

    BuzzLeclaire
    Pense a adapter le code proposé ton code est cent fois plus lent ...en fin si tu veux gagner de temps
    Tu peux aussi enregistrer les résultats sur un nouveau fichier pour ne pas répéter les mêmes opérations...

  6. #86
    Membre éprouvé Avatar de BuzzLeclaire
    Homme Profil pro
    Dev/For/Vte/Ass
    Inscrit en
    Août 2008
    Messages
    1 606
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Dev/For/Vte/Ass

    Informations forums :
    Inscription : Août 2008
    Messages : 1 606
    Points : 1 113
    Points
    1 113
    Par défaut
    Re,

    J'ai finalisé le vrai record de mes fichiers initaux (1254 octets la ligne) et je testerais vos 2 solutions ce soir dans mon outils et je vous dirais.


  7. #87
    Membre éprouvé
    Avatar de Dr.Who
    Inscrit en
    Septembre 2009
    Messages
    980
    Détails du profil
    Informations personnelles :
    Âge : 45

    Informations forums :
    Inscription : Septembre 2009
    Messages : 980
    Points : 1 294
    Points
    1 294
    Par défaut
    Buzz, tu es sous Delphi 2009 :


    alors j'ai la solution pour 175 milles lignes :

    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
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
     
    uses
      FView, 
      Generics.Collections; // <-- ICI
     
     
    type
      TNumCompteBin = packed array[0..8] of byte; // <-- ICI
      TNumFactBin = packed array[0..7] of byte; // <-- ICI
     
      PFileStruct = ^TFileStruct;
      TFileStruct = packed record case integer of
        0 : ( Buffer : array[0..22] of AnsiChar);
        1 : (
              NumFact   : packed record case integer of
                0: (NumFact : array[0..7] of AnsiChar);
                1: (Binary : TNumFactBin); // <-- ICI
              end;
              NumCompte : packed record case integer of
                0:( NumCompte : array[0..8] of AnsiChar);
                1:( Binary : TNumCompteBin);  // <-- ICI
              end;
              Date      : packed record case integer of
                0: (FullDate : array[0..5] of AnsiChar);
                1: (D,M,Y    : array[0..1] of AnsiChar);
              end;
              CRLF : word;
            );
      end;
     
    type
      TNumCompteBinList = TList<TNumCompteBin>; // <-- ICI
      TNumFactBinList = TList<TNumFactBin>; // <-- ICI
     
     
    const
      SizeOfFileStruct = SizeOf(TFileStruct);
     
     
    var
      FV : TFileView;
      Count : integer;
     
    function TestFileStruc: string;
    var ptr : PFileStruct;
        N,C : integer;
        G   : cardinal;
        LNCBin : TNumCompteBinList; // <-- ICI
        LNFBin : TNumFactBinList; // <-- ICI
    begin
      G := GetTickCount;
      C := 0;
     
      LNCBin := TNumCompteBinList.Create; // <-- ICI
      FV := TFileView.Create(ExtractFilePath(ParamStr(0))+'DatasFS.bin');
      try
        if FV.Loaded then
        begin
          Count := FV.FileSize div SizeOfFileStruct;
          Ptr   := FV.View;
          for N := 0 to Count do
          begin
           if LNCBin.IndexOf(ptr^.NumCompte.Binary) < 0 then
             LNCBin.Add(ptr^.NumCompte.Binary); // <-- ET ICI!
           inc(ptr);
          end;
          C := LNCBin.Count;
        end;
      finally
        FV.Free;
        LNCBin.Free;
      end;
     
      G := GetTickCount - G;
      result := format('%d ms : %d factures et %d doublons (%d ajoutées)',[G, Count+1, (Count+1)-C, C]);
    end;

    bien sur ceux qui n'ont pas D2009 ne pourront pas tester ce code.
    Les types generiques n'étant pas disponible pour des delphi plus vieux.

    je trouve que la TList generique est même un chouille plus rapide que TList.

    donc chaque champs pourrait avoir sa Liste et sa propriété Binaire (binary de type array[..] of byte).

  8. #88
    Membre éprouvé Avatar de BuzzLeclaire
    Homme Profil pro
    Dev/For/Vte/Ass
    Inscrit en
    Août 2008
    Messages
    1 606
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Dev/For/Vte/Ass

    Informations forums :
    Inscription : Août 2008
    Messages : 1 606
    Points : 1 113
    Points
    1 113
    Par défaut
    Donc voici mes tests :

    Taille fichier test : 113 724 000 octets
    Taille d'une ligne : 25 octets
    Nombre de Ligne : 4 548 960

    (1)La Méthode (Dr.Who) Buzz ajout de ListString.Duplicates := dupIgnore;
    Gestion des doublons : Oui
    Tri de la liste en fin : Oui par ajout d'une Stringlist (ListString.Sorted := True);
    Essai Temps n°1 : 3765 ms
    Essai Temps n°2 : 3406 ms
    Essai Temps n°3 : 3438 ms
    Temps : 3536 ms

    (2)La Méthode Dr.Who (Hi, Lo : LongWord);
    Gestion des doublons : Oui
    Tri de la liste en fin : Oui par ajout d'une Stringlist (ListString.Sorted := True);
    Essai Temps n°1 : 188 ms
    Essai Temps n°2 : 172 ms
    Essai Temps n°3 : 172 ms
    Temps : 177 ms
    Remarque : Pas certain en terme de doublon

    (3)La Méthode Montor - TStringHash
    Gestion des doublons : Oui
    Tri de la Liste en fin : Nom (pas de Sort possible);
    Essai Temps n°1 : 1563 ms
    Essai Temps n°2 : 1531 ms
    Essai Temps n°3 : 1516 ms
    Temps : 1536 ms
    Remarque : Comment gérer le tri ?

    (4)La Méthode Gilbert - Par boucle
    Gestion des doublons : Oui
    Tri de la Liste en fin : ???? (A voir)
    Essai Temps n°1 : 2641 ms
    Essai Temps n°2 : 2625 ms
    Essai Temps n°3 : 2625 ms
    Temps : 2630 ms
    Remarque : La liste retourne dés pointeur et pas les données

    (5)La Méthode Dr.Who - D2009
    Gestion des doublons : Oui
    Tri de la liste en fin : Oui par ajout d'une Stringlist (ListString.Sorted := True);
    Essai Temps n°1 : 297 ms
    Essai Temps n°2 : 250 ms
    Essai Temps n°3 : 282 ms
    Temps : 276 ms

    Méthode 4 : La plus rapide avec résultat correcte et certain
    Méthode 3 : fonctionne Manque le tri (ce qui pourrais augmenter le traitement)
    Méthode 1 : La plus lente Résultat correcte et certain

    Méthode 2 et 4 n'apporte pas un bon résultat, où le résultat n'ai pas sur


    J'attends vos commentaires...

  9. #89
    Membre éprouvé
    Avatar de Dr.Who
    Inscrit en
    Septembre 2009
    Messages
    980
    Détails du profil
    Informations personnelles :
    Âge : 45

    Informations forums :
    Inscription : Septembre 2009
    Messages : 980
    Points : 1 294
    Points
    1 294
    Par défaut
    petite erreur sur la methode la plus rapide (4) et non 5

    pour le tri

    -> TList avec les pointeurs récupéré sur les entrées hors doublons -> ajout d'une methode de Tri pour TList.Sort.


    dans la condition de gestion des doublons :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    -> boucle de lecture
    if .... pas doublons ... then
    begin
     -> Ajouter Ptr^.Champ à une anti-doublons TList<typechamp>(DblList<champ>.add(Ptr^.Champ)
     -> Ajouter Ptr à une  TList<PFileStruct> (PtrList.Add(ptr))
    end;
    -> fin boucle
    -> liberer DblList
    -> PtrList.Sort(MethodeComparerChamp);
    la methode de comparaison se fera comme cela exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    function CompareStrucByChamp(const P1, P2: pointer): integer;
    begin
      if PFileStruc(P1)^.Champ > PFileStruc(P2)^.Champ then
        result := 1
      else
      if PFileStruc(P1)^.Champ < PFileStruc(P2)^.Champ then
        result := -1
      else
        result := 0;
    end;
    bien sur on pourrait faire comme ça ce serait genial, mais les champs etant du texte il faudrat chercher les methodes de comparaisons adequate et performante.

  10. #90
    Membre éprouvé Avatar de BuzzLeclaire
    Homme Profil pro
    Dev/For/Vte/Ass
    Inscrit en
    Août 2008
    Messages
    1 606
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Dev/For/Vte/Ass

    Informations forums :
    Inscription : Août 2008
    Messages : 1 606
    Points : 1 113
    Points
    1 113
    Par défaut
    Citation Envoyé par Dr.Who Voir le message
    petite erreur sur la methode la plus rapide (4) et non 5
    Euh.. en fait Métode 5 est la plus rapide D 2009


  11. #91
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 266
    Points
    3 266
    Par défaut
    Bonjour,

    C'est fini ???

    A+.

  12. #92
    Membre éprouvé Avatar de BuzzLeclaire
    Homme Profil pro
    Dev/For/Vte/Ass
    Inscrit en
    Août 2008
    Messages
    1 606
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Dev/For/Vte/Ass

    Informations forums :
    Inscription : Août 2008
    Messages : 1 606
    Points : 1 113
    Points
    1 113
    Par défaut
    Citation Envoyé par Gilbert Geyer Voir le message
    Bonjour,

    C'est fini ???

    A+.
    Je pense que oui.

    Je peux mettre ici mon unit qui comprends
    - La méthode 5
    - La gestion multifichier
    - l'envoi dans un stringgrid du résultat.

    ou même mettre les 5 solutions différente ?


  13. #93
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 266
    Points
    3 266
    Par défaut
    Re-bonjour,

    1)
    Je pense que oui.
    Je pensais que tu donnerais une suite à la dernière proposition d'aujourd'hui 01h25 de Dr Who :

    pour le tri

    -> TList avec les pointeurs récupéré sur les entrées hors doublons
    2)
    Je peux mettre ici mon unit qui comprends
    - La méthode 5
    - La gestion multifichier
    - l'envoi dans un stringgrid du résultat.

    ou même mettre les 5 solutions différente ?
    A mon avis La méthode 5 + La gestion multifichier + l'envoi dans un stringgrid du résultat ça devrait suffire comme conclusion, ... les 5 solutions différentes ça risque de faire trop.

    A+.

  14. #94
    Membre éprouvé Avatar de BuzzLeclaire
    Homme Profil pro
    Dev/For/Vte/Ass
    Inscrit en
    Août 2008
    Messages
    1 606
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Dev/For/Vte/Ass

    Informations forums :
    Inscription : Août 2008
    Messages : 1 606
    Points : 1 113
    Points
    1 113
    Par défaut
    Citation Envoyé par Gilbert Geyer Voir le message
    Re-bonjour,
    1)
    Je pensais que tu donnerais une suite à la dernière proposition d'aujourd'hui 01h25 de Dr Who :
    au vue de ce qu'a écris Dr.Who en pied du post :
    bien sur on pourrait faire comme ça ce serait genial, mais les champs etant du texte il faudrat chercher les methodes de comparaisons adequate et performante.
    J'ai pas pousser plus avant...

    A mon avis La méthode 5 + La gestion multifichier + l'envoi dans un stringgrid du résultat ça devrait suffire comme conclusion, ... les 5 solutions différentes ça risque de faire trop.
    Voilà le tous :

    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
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
      type
      TNumCompteBin = packed array[0..8] of byte;
     
      PFileStruc = ^TFileStruc;
      TFileStruc = packed record
                private __NumFact        : array[0..7]   of AnsiChar; // 8
                public NumCompte :
                        packed record case integer of
                       0:( NumCompte : array[0..8] of AnsiChar);
                       1:( Binary : TNumCompteBin);  // <-- ICI
                       end;
                private __Date           : array[0..5]   of AnsiChar; // 6
                private __LibelleManuel  : array[0..59]  of AnsiChar; // 60
                private __Debit          : array[0..19]  of AnsiChar; // 20
                private __Credit         : array[0..19]  of AnsiChar; // 20
                private __RepEcheances   : array[0..259] of AnsiChar; // 260
                private __RepAnalytique  : array[0..399] of AnsiChar; // 400
                private __Devise         : array[0..7]   of AnsiChar; // 8
                private __Cours          : array[0..19]  of AnsiChar; // 20
                private __LibellePiece   : array[0..59]  of AnsiChar; // 60
                private __FlagPiece      : array[0..0]   of AnsiChar; // 1
                private __Quantite       : array[0..14]  of AnsiChar; // 14
                private __Unite          : array[0..2]   of AnsiChar; // 3
                private __Reserve        : array[0..29]  of AnsiChar; // 30
                private __FinECR         : array[0..1]   of AnsiChar; // 2
                private __NomLogiciel    : array[0..59]  of AnsiChar; // 60
                private __CodeDossier    : array[0..59]  of AnsiChar; // 60
                private __TypeDeLaPiece  : array[0..59]  of AnsiChar; // 60
                private __IdentDGI       : array[0..29]  of AnsiChar; // 30
                private __InfoLibre      : array[0..119] of AnsiChar; // 120
                private __FinLigne       : array[0..1]   of AnsiChar; // 2
              end;
      function CompteNodup(Fichier: TStringList): TStringList;
     
    type
      TNumCompteBinList = TList<TNumCompteBin>;
     
    Const
      SizeOfFileStruc = SizeOf(TFileStruc);
     
     
    // ...
     
    function CompteNodup(Fichier: TStringList): TStringList;
    var
      FV  : TFileView;
      Ptr : PFileStrucI;
      I, N : Integer;
      Count: Int64;
      LNCBin   : TNumCompteBinList;
    begin
      Result := TStringList.Create;
      Result.Sorted := True;
    //  Result.Duplicates := dupIgnore; // Puisque gestion de doublon par LNCBin
      for I := 0 to Fichier.Count - 1 do
        Begin
        LNCBin := TNumCompteBinList.Create;
        FV  := TFileView.Create(Trim(Fichier[i]));
        try
          if FV.Loaded then
          begin
            Count := ((FV.FileSize) div SizeOfFileStruc); // nombre d'elements
            Ptr := FV.View;
            for N := 0 to count-1 do
            begin
               if LNCBin.IndexOf(ptr^.NumCompte.Binary) < 0 then
               Begin
                LNCBin.Add(ptr^.NumCompte.Binary);
                Result.Add(Ptr^.NumCompte.NumCompte);
               end;
               Inc(Ptr);
            end;
          end;
        finally
          FV.Free;
          LNCBin.Free;
        end;
      end;
    end;
    Utilisation :

    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
    procedure TForm1.BtnClick(Sender: TObject);
    Var
      Fichiers   : TStringList;
      Comptes : TStringList;
      i: Integer;  
    Begin
        Fichiers := TStringList.Create; // On construit la liste des fichiers à envoyer
        Comptes := TStringList.Create; // On récupèr les comptes sans doublons
        Try
          for i := 0 to ListBoxFichierSource.Count - 1 do
            Fichiers.Insert(i,ListBoxFichierSource.Items.Strings[i]);
     
          Comptes := CompteNodup(Fichiers);
          StringGridComptes.rowCount := Comptes.Count;
     
          for i := 0 to Comptes.Count - 1 do
          Begin
            StringGridComptes.Cells[0,i+1] := Comptes.Strings[i];
          end;
     
        Finally
          comptes.Free;
          Fichiers.Free;
        End;
    end;
    Cela sous entends que vous avez un listbox qui récupère des fichiers (avec opendialog) et que vous disposer d'un Stringgrid.


  15. #95
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 266
    Points
    3 266
    Par défaut
    Re-Salut,

    Merci pour le code : Il marche également sous Delphi 5 ?

    mais les champs etant du texte il faudrat chercher les methodes de comparaisons adequate et performante.
    ... on peut essayer avec m:=CompareString() : Voir dans l'Aide Delphi.

    Exemple où CompareString est utilisée pour rechercher le nombre d'occurrence des mots-cibles déclarés dans l'array MotsCibles qui est renvoyé avec les nombres d'occurrences :

    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
    procedure RechercheOccurences(Texte : string; var MotsCibles : array of string);
    var       i,j,m,n:integer;
    begin
         for i:=Low(MotsCibles) to High(MotsCibles) do
           begin
             n:=0;
             for j:=1 to length(Texte) do
               begin
                if Texte[j]=MotsCibles[i,1] then
                   begin
                     m:=CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, @MotsCibles[i,1],
                                      Length(MotsCibles[i]), @Texte[j], Length(MotsCibles[i]));
                     if (m=2) then inc(n);
                   end;
               end;
             MotsCibles[i]:=MotsCibles[i]+' Trouvé : '+inttostr(n)+' fois';
           end;
    end;
    m:=CompareString() vaut
    1 si la première chaine "pèse" moins que la deuxième,
    2 si elles sont égales,.
    3 si la première chaine "pèse" plus que la deuxième.

    A+.

  16. #96
    Membre éprouvé Avatar de BuzzLeclaire
    Homme Profil pro
    Dev/For/Vte/Ass
    Inscrit en
    Août 2008
    Messages
    1 606
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Dev/For/Vte/Ass

    Informations forums :
    Inscription : Août 2008
    Messages : 1 606
    Points : 1 113
    Points
    1 113
    Par défaut
    Citation Envoyé par Gilbert Geyer Voir le message
    Re-Salut,

    Merci pour le code : Il marche également sous Delphi 5 ?
    Non, malheureusement la méthode 5 la plus élaboré (Dr.Who) ne fonctionne que pour Delphi 2009 et +
    car tu doit déclarer dans tes uses
    Generics.Collections; pour faire marché
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    type
      TNumCompteBinList = TList<TNumCompteBin>;
    Pour delphi 5, il faut récupérer la procédure de TStringHash à intégrer dans Inifiles.pas et utilisé la méthode de Montor.

    Maintenant j'ai pas regardé du coté de StringCompare...

  17. #97
    Membre éprouvé
    Avatar de Dr.Who
    Inscrit en
    Septembre 2009
    Messages
    980
    Détails du profil
    Informations personnelles :
    Âge : 45

    Informations forums :
    Inscription : Septembre 2009
    Messages : 980
    Points : 1 294
    Points
    1 294
    Par défaut
    ma derniere methode peut fonctionner avec les Delphi < 2009

    en supprimant l'unité Generics.Collections et en derivant Classes.TList pour le(s) type(s) de gestion de doublons.

    et bien sur remplacer les déclarations de type génériques par les bonnes vieilles classes dérivées ou perso.

  18. #98
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 266
    Points
    3 266
    Par défaut
    Bonjour,

    A BuzzLeclaire et à Dr.Who : Merci pour vos explications.

    A+.

  19. #99
    Membre éprouvé
    Avatar de Montor
    Homme Profil pro
    Autre
    Inscrit en
    Avril 2008
    Messages
    879
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Autre

    Informations forums :
    Inscription : Avril 2008
    Messages : 879
    Points : 963
    Points
    963
    Par défaut
    un resultat que je n'attendais pas ce n'est pas un vrai test...le test doit se fait sur un fichier le premier contient 100% de doublons et l'autre qui n'a aucun doublon si tu veux evter des surprises mes tests n'ont jamais depassé 40Mb... avec les fonction 1 ,2 de DrWho le temps etait vraiment terrible... la puissance de TSringHash est dans les operations de test rapide... pour la tri c'est le classique sort sur Tlist mais cela resolu ton probleme c'est la chose la plus importante...

  20. #100
    Membre éprouvé Avatar de BuzzLeclaire
    Homme Profil pro
    Dev/For/Vte/Ass
    Inscrit en
    Août 2008
    Messages
    1 606
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Dev/For/Vte/Ass

    Informations forums :
    Inscription : Août 2008
    Messages : 1 606
    Points : 1 113
    Points
    1 113
    Par défaut
    Citation Envoyé par Montor Voir le message
    un resultat que je n'attendais pas ce n'est pas un vrai test...le test doit se fait sur un fichier le premier contient 100% de doublons et l'autre qui n'a aucun doublon si tu veux evter des surprises mes tests n'ont jamais depassé 40Mb... avec les fonction 1 ,2 de DrWho le temps etait vraiment terrible... la puissance de TSringHash est dans les operations de test rapide... pour la tri c'est le classique sort sur Tlist mais cela resolu ton probleme c'est la chose la plus importante...
    Par acquis de conscience j'ai regardé avec un fichier ne comportant aucun doublon.

    Eh bien tu as raison Montor !!
    Je mettais focalisé sur un fichier ne comportant pratiquement que des doublons. Dans ce cas c'est StringHash le plus rapide sans aucune comparaison.

    Fichier de 765 ko comportant 30113 lignes (par énorme).

    (1)La Méthode (Dr.Who) Buzz ajout de ListString.Duplicates := dupIgnore;
    Essai Temps n°1 : 6985 ms
    Essai Temps n°2 : 2484 ms
    Essai Temps n°3 : 2296 ms
    Temps : 3921 ms

    (2)La Méthode Dr.Who (Hi, Lo : LongWord);
    Essai Temps n°1 : 297 ms
    Essai Temps n°2 : 266 ms
    Essai Temps n°3 : 266 ms
    Temps : 276 ms
    Résultat erroné manque la moitié des données.

    (3)La Méthode Montor - TStringHash
    Essai Temps n°1 : 1359 ms
    Essai Temps n°2 : 1344 ms
    Essai Temps n°3 : 1375 ms
    Temps : 1359 ms

    (4)La Méthode Gilbert - Par boucle
    Essai Temps n°1 : 69469 ms
    Essai Temps n°2 : 70375 ms
    Essai Temps n°3 : 71345 ms
    Temps : 70396 ms !!!

    (5)La Méthode Dr.Who - D2009
    Essai Temps n°1 : 5984 ms
    Essai Temps n°2 : 6000 ms
    Essai Temps n°3 : 5953 ms
    Temps : 5979 ms

    Résultat
    1)(3)La Méthode Montor - TStringHash : Temps : 1359 ms
    2)(1)La Méthode (Dr.Who) Buzz : Temps : 3921 ms
    3)(5)La Méthode Dr.Who - D2009 : Temps : 5979 ms

    Commentaire :
    (1)Si ta méthode permettait un tri dans l'ordre croissance se serais vriament pas mal. Pour le 2 Un simple Stringlist := dupignore, devient plus rapide que le (3)

    Cela n'enlève rien à la notion de structure de fichier par record qui simplifie la vie à ces 3 procédures.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Demande de conseil pour migration de lignes vers colonnes
    Par ririd dans le forum Administration
    Réponses: 6
    Dernier message: 04/11/2004, 18h02
  2. [Struts_Tiles VS CSS] Demande de Conseils
    Par sylvain_neus dans le forum Struts 1
    Réponses: 4
    Dernier message: 16/04/2004, 11h12
  3. [sqlbaseserver]demande de conseils/aides pour requêtes
    Par GéniuS77 dans le forum Langage SQL
    Réponses: 14
    Dernier message: 18/03/2004, 18h27
  4. demande de conseil
    Par stephane eyskens dans le forum EDI/Outils
    Réponses: 2
    Dernier message: 25/09/2003, 15h18

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