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 :

Recherche de string dans plusieurs fichiers (findstr like)


Sujet :

Langage Delphi

  1. #1
    Membre régulier
    Profil pro
    Directeur
    Inscrit en
    Juin 2005
    Messages
    113
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Directeur

    Informations forums :
    Inscription : Juin 2005
    Messages : 113
    Points : 87
    Points
    87
    Par défaut Recherche de string dans plusieurs fichiers (findstr like)
    Bonjour à tous,
    Je me demandais comment faire pour rechercher une chaine de caractaires dans tous les fichiers d'un dossier via delphi (un peu l'équivalent de la commande findstr de l'invite de commande) et retourner le/les fichiers correspondant(s) pour modifier cette chaine(une fois que j'arrive retourner le non du fichier, ne vous en faites pas, je sais comment l'ouvrir et modifier la chaine ). J'ai fais quelques recherches sur google et sur ce site, je n'ai rien trouvé qui ne me donne ne serait-ce qu'un indice ... Pouriez-vous me mettre sur la voie svp ? Que ce soit en delphi pur ou en winapi mais que ca reste le plus légé possible svp.

    Merci pour tout

  2. #2
    Membre régulier
    Profil pro
    Directeur
    Inscrit en
    Juin 2005
    Messages
    113
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Directeur

    Informations forums :
    Inscription : Juin 2005
    Messages : 113
    Points : 87
    Points
    87
    Par défaut
    Je complete un peu mon poste en vous donnant mon idee que j'apprecie que tres peu car tres longue et "couteuse" en ressources je pense: lister le dossier, pour chaque fichier, l'ouvrir dans un stream, faire un pos(), si pos() est different de 0 alors la chaine existe, donc donner le nom du fichier (ou alors, tant qu'on y est, directement remplacer la chaine)

  3. #3
    Membre chevronné
    Avatar de Clorish
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    2 474
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 2 474
    Points : 2 158
    Points
    2 158
    Par défaut
    Je ne vois pas comment on peut faire autrement
    A moins de creer une sorte de table de hashage listant les mots contenus dans chaques fichiers.

    Cela prends un certain temps pour mettre a jour la table mais la recherche est plus rapide. Bien sur l'ideal est de conserver cette table d'une recherche a l'autre ....

  4. #4
    Expert éminent sénior
    Avatar de Cl@udius
    Homme Profil pro
    Développeur Web
    Inscrit en
    Février 2006
    Messages
    4 878
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Février 2006
    Messages : 4 878
    Points : 10 008
    Points
    10 008
    Par défaut
    Salut

    Une idée comme ça !
    Et si tu utilisais cette bonne vieille commande DOS FindStr en redirigeant l'echo vers un fichier texte ?

    Tu disposerais ainsi de la liste des fichiers qui t'intéressent.

    @+ Claudius

  5. #5
    Membre chevronné
    Avatar de Clorish
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    2 474
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 2 474
    Points : 2 158
    Points
    2 158
    Par défaut
    Petite idee ... si as acces au mode d'enregistrement des fichiers, peut etre peut tu generer lors de l'enregistrement une table d'index des mots : une suite de numeros indiquant la position de depart de chaques mots du fichier.
    La recherche sera plus rapide car il te suffit de tester le premier caractere et si different, sauter directement au mot suivant.

    Rajoute en plus de la position la taille du mot pour ne tester que les mots de meme taille.

  6. #6
    Membre régulier
    Profil pro
    Directeur
    Inscrit en
    Juin 2005
    Messages
    113
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Directeur

    Informations forums :
    Inscription : Juin 2005
    Messages : 113
    Points : 87
    Points
    87
    Par défaut
    @Cl@udius > J'ai pensé a ca oui mais je me suis dit que ca serait pas assez drole ^^
    @Clorish > Dsl, j'ai pas tout compris a ce que tu as dit. Il faut savoir que la recherche ne sera faite qu'une fois par pc/dossier et que donc, rien ne sert de stocker les infos

  7. #7
    Membre chevronné
    Avatar de Clorish
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    2 474
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 2 474
    Points : 2 158
    Points
    2 158
    Par défaut
    je ne comprends pas trop ton probleme en fait.
    si elle ne doit etre fait qu'une seule fois par PC et dossier, ou est l'interet de gagner en rapidité ?
    Il suffit de planifier la recherche la nuit, et apres ca peux prendre 12h .. et alors ?

    Par contre si tu dois regulierement faire des recherches la oui ca a un interet.
    Et pour accelerer la recherche il faut eviter de faire des choses inutiles, comme tester des mots dont on sait qu'il ne conviennet pas.

    Si tu compare "toto" (4 lettre) face a un mot qui en fait 5 tu peux etre sur que ce mot n'est pas toto. Donc inutile de le comparer.

    De meme, si le mot commence par AXXX alors ca ne peut pas etre "toto" donc encore une fois inutile a comparer.

    Maintenant si on connait avant de scanner le fichier le nombre de mots = 4 et leurs positions dans le fichier (par exemple 3 mots aux positions 15, 200 et 515) il te suffit de tester au mieux 3 caracteres au pire 12 en faisant des jum dans le fichier de 0 à 15 puis 200 puis 512

    Comparatif : 1 fichier avec 100 mots avec une moyenne de 4 caracteres par mots soit 400 octets.
    Ca te demande 100 iterations pour reperer les mots susceptibles d'etre celui recherché plus quelques iteration de plus pour les tester.
    On gagne pas mal par rapport a une analyse des 400 caracteres du fichier... (envirion 50 a 75%).

    Bon bien sur, cela depends de la frequence des mots candidats et de leurs graphie.

    Un fichier contenant 100 mots, tous de 4 lettres avec 1 toto et que des toti .... ca risque de pas le faire :p
    Par contre un fichier de 99 mots de 5 lettres et un seul de 4 (toto) la recherche sera tres rapide !

    A voir

  8. #8
    Membre régulier
    Profil pro
    Directeur
    Inscrit en
    Juin 2005
    Messages
    113
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Directeur

    Informations forums :
    Inscription : Juin 2005
    Messages : 113
    Points : 87
    Points
    87
    Par défaut
    Je suis sur la voie

    J'ai juste un petit pb, je fait un findstr et je load le fichier dans un string (via TStream.read), le pb c que ce le fichier est composé du chemin du fichier en question + un retour chariot. J'ai essayé:
    delete(MonString, pos(chr(13), MonString), 1); et
    delete(MonString, lenght(MonString), 1); et
    delete(MonString, tmp, 1); [ tmp := length(MonString) - 1; ]
    Et ce retour chariot est tjs la :/

  9. #9
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 577
    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 577
    Points : 25 225
    Points
    25 225
    Par défaut
    Tu peux regarder ce sujet , j'ai écrit une fonction SearchStringInFile pour chercher dans un fichier

    tient, j'ai un code plus récent (j'ai aussi une variante pour des fichiers de plus de 2Go), alors, malheureusement, il faut parcourir, les fichiers, mais tu dois pouvoir, lancer la recherche de 2-3 fichiers en thread avec un buffer de 64Ko ou lieu de 1Ko, ainsi le temps que l'un lit le DD, l'autre consomme du processeur, ainsi de suite ... en terme de performance disons, que j'ai fait des tests sur des fichiers de 100Mo et ça dépasse pas la seconde ...

    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
    function SearchStringInFile(const FileName: string; SearchString: string; out OffSets: TIntegerDynArray; KeepOffSet: Boolean = False; CaseSensitive: Boolean = True): Integer;
    const
       BUF_SIZE: Integer = 1024;
    var
       FileToSearch: file;
       SearchBuf: array of Char;
       iSearchBufPos, iSearch, iMark, iCountFound, iRememberFound, iReaded: Integer;
       SearchLen: Integer;
       AmtTransferred: Integer;
       FileModeCopy: Byte;
    begin
       Result := 0;
       iReaded := 0;
     
       SetLength(SearchBuf, BUF_SIZE);
       SearchLen := Length(SearchString);
       if not CaseSensitive then
         SearchString := SysUtils.UpperCase(SearchString);
     
       FileModeCopy := FileMode;
       FileMode := SysUtils.fmOpenRead;
       try
         AssignFile(FileToSearch, FileName);
         Reset(FileToSearch, 1);
         try
            iCountFound := 0;
     
            while not Eof(FileToSearch) do
            begin
               BlockRead(FileToSearch, SearchBuf[0], BUF_SIZE, AmtTransferred); // [0] parce que c'est un tableau dynamique
               iRememberFound := iCountFound;
               iSearchBufPos := 0;
     
               while iSearchBufPos < AmtTransferred do
               begin
                  // Comparaison Octet par Octet de la chaine recherchée
                  for iMark := iCountFound + 1 to SearchLen do
                  begin
                     iSearch := iSearchBufPos + iMark - iRememberFound - 1;
                     if iSearch >= AmtTransferred then
                        Break;
     
                     if (CaseSensitive and (SearchBuf[iSearch] = SearchString[iMark]))
                     or (not CaseSensitive and (UpCase(SearchBuf[iSearch]) = SearchString[iMark])) then
                     begin
                        Inc(iCountFound);
     
                        if iCountFound >= SearchLen then
                        begin
                           Inc(Result);
                           if KeepOffSet then
                           begin
                              SetLength(OffSets, Length(OffSets) + 1);
                              OffSets[High(OffSets)] := iReaded + iSearchBufPos - iRememberFound;
                           end;
                           iCountFound := 0;
                           iRememberFound := 0;
                           Break;
                        end;
                     end else begin
                        iCountFound := 0;
                        iRememberFound := 0;
                        Break;
                     end;
                  end;
                  Inc(iSearchBufPos, iCountFound + 1);
               end;
               Inc(iReaded, AmtTransferred);
            end;
         finally
            CloseFile(FileToSearch);
         end;
       finally
         FileMode := FileModeCopy;
       end;
    end;

  10. #10
    Membre régulier
    Profil pro
    Directeur
    Inscrit en
    Juin 2005
    Messages
    113
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Directeur

    Informations forums :
    Inscription : Juin 2005
    Messages : 113
    Points : 87
    Points
    87
    Par défaut
    Merci pour ton aide, je vais essayer de voir si j'arrive continuer comme j'ai commencé histoire de me dire que c'est mon code J'ai juste ce probleme de retour chariot, je capte pas pq j'arrive pas le del :/

  11. #11
    Membre régulier
    Profil pro
    Directeur
    Inscrit en
    Juin 2005
    Messages
    113
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Directeur

    Informations forums :
    Inscription : Juin 2005
    Messages : 113
    Points : 87
    Points
    87
    Par défaut
    Ca y est, c'est résolu, j'ai utilisé trim()

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

Discussions similaires

  1. [Batch] Recherche d'une string dans plusieurs fichiers
    Par zenzedoon dans le forum Scripts/Batch
    Réponses: 1
    Dernier message: 29/12/2012, 16h14
  2. Logiciel de recherche d'expression dans plusieurs fichiers
    Par Deciprog dans le forum Autres Logiciels
    Réponses: 2
    Dernier message: 31/03/2010, 16h23
  3. Recherche de valeurs dans plusieurs fichiers
    Par Trooper2 dans le forum Macros et VBA Excel
    Réponses: 33
    Dernier message: 04/07/2007, 12h04
  4. Module de recherche de mots dans plusieurs fichiers
    Par hat_et_m dans le forum Autres Logiciels
    Réponses: 1
    Dernier message: 24/09/2006, 20h09

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