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

VB 6 et antérieur Discussion :

Recherche dans un fichier texte volumineux.


Sujet :

VB 6 et antérieur

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    49
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 49
    Points : 29
    Points
    29
    Par défaut Recherche dans un fichier texte volumineux.
    bonjour,

    voilà, j'ai réalisé une interface VB qui permet de faire du tri sur les données d'un fichier (je ne doit pas installer de moteur de base de donnée sur le poste en question).

    Le fichie se compose de lignes relativmeent courtes ( 100aine de char), divisés en trois champs ...

    Mon interface , permet de saisire distinctement (style multicritère) une valeur ou les trois .
    une recherche est donc éffectuée, ligne par ligne en matchant les valeur aux données rencontrées entièrement ou sur une partie..
    et affiche les lignes trouvées qui correspondent à ces critère de recherche dans un grid...

    vu les tailles de fichier annoncées (20 000 à 200 000 lignes) , j'ai remplacé la rechercche bète et méchante en ligne à ligne de tout le fichier à chaque fois , par le chargement du contenu de mon fichier au démarrage de l'interface dans un recordset virtuel composé de trois champs (recordset décalré dans une class).

    ensuite à saisie des valeurs de recherche , je parcours mon recordset virtuel .

    Mon pb aujourd'hui, j'ai été obligé de rpasser en recherche ligne à ligne car le fichier qui m'a été soumis fait 1 600 000 lignes...et le chargement du fichier dans le recordset bouffe toute la mémoire et prend plus de 5 min.

    Là avec une recherche sur le fichier à chaques fois , et en optimisant au max le code , il met 45 secondes pour parcourir tout le fichier et me rendre les lignes matchées par les critères renseignés....

    La question : y a t- il un moyen plus rapide de recherche de valeur à l'intérieur de fichier...ou de pouvoir créer par code une mini base de donnée temporaire.

    un peu long à lire , merci pour ceux qui sont allé au bout et qui pourront répondre.

  2. #2
    Membre éclairé Avatar de sozie9372
    Inscrit en
    Mai 2005
    Messages
    713
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Mai 2005
    Messages : 713
    Points : 724
    Points
    724
    Par défaut
    Salut !

    Je vois a peu près ce que tu veux dire, mais il y a un truc que je n'ai pas compris, tu parles de recordSet virtuel que tu charges (et qui n'a pas porté ses fruits) au démarrage et à la fin de ton post tu parles de réutiliser une base de données.
    J'ai sûrement du mal...
    Sinon, si je ne suis pas trop HS, est-ce que tu as utilisé ton fichier comme base de données (avec un driver pour fichiers textes) ? Ca te permet avec un fichier disposé comme ca (Style csv):
    MONCHAMP1;MONCHAMP2;MONCHAMP3 // Ici les noms des champs
    MAVALEUR11;MAVALEUR21;MAVALEUR31 // Ici les valeurs...
    MAVALEUR12;MAVALEUR22;MAVALEUR32
    MAVALEUR13;MAVALEUR23;MAVALEUR33
    de l'utiliser comme une base de données.
    Un exemple de 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
     
    Dim Cnx As ADODB.Connection
    '-------------------------------------------------
    Public Sub open_connection(aPath As String)
    ' $ Open the connection and select the driver switch the databaseType
        Set Cnx = New ADODB.Connection
        Cnx.Open "DRIVER={Microsoft Text Driver (*.txt; *.csv)};" & _
                    "DBQ=" + aPath + ";", "", ""
        If Not Cnx.State = adStateOpen Then
           MsgBox "Ya comme un problème...", , "Error"
           End
        End If
    End Sub
     
    '-------------------------------------------------
    Public Sub close_connection()
    ' $ Close the connection
      If Cnx.State = 1 Then Cnx.Close
      Set Cnx = Nothing
    End Sub
     
    '-------------------------------------------------
    Public Function execQuery(query As String) As ADODB.Recordset
    ' $ To execute a query
        Dim rs As ADODB.Recordset
        Set rs = New ADODB.Recordset
        rs.Open query, Cnx
        Set execQuery = rs
    End Function
     
    '-------------------------------------------------
    ' le fichier "monFichier.txt" est dans le répertoire de l'application
    Public Sub test()
       Dim rs As ADODB.Recordset
       Dim query As String
       open_connection App.path
       query = "SELECT * FROM [monFichier#txt] WHERE CHAMP1='MAVALEUR13'"
       Set rs = execQuery query
       While Not rs.EOF
           Debug.print "résultat : " & rs.Fields(0) & " " & rs.Fields(1)
           rs.moveNext
       Wend
       close_connection
    End Sub
    J'ai repris un code a moi que j'ai modifié en live pour l'exemple, si il y a des bugs tiens moi au courant, je le referai... J'espère avoir répondu à ta question.
    +++
    Ju
    "Il y a 3 personnes en ce monde sur qui tu peux compter : moi, le pape et le cavalier solitaire ! "
    Penser à svp

  3. #3
    Membre éclairé Avatar de sozie9372
    Inscrit en
    Mai 2005
    Messages
    713
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Mai 2005
    Messages : 713
    Points : 724
    Points
    724
    Par défaut
    Ah oui j'oubliais, il faut rajouter la référence ADODB à ton projet, ca doit être Active Data Object ou un truc du style
    +++
    Ju
    "Il y a 3 personnes en ce monde sur qui tu peux compter : moi, le pape et le cavalier solitaire ! "
    Penser à svp

  4. #4
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    49
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 49
    Points : 29
    Points
    29
    Par défaut
    non tu n'es pas HS , et je n'avais pas pensé à utilisé mon fichier sous forme base de donnée.. en faite les colonnes ne sont aps clairemetn délimitées comme un CSV....mais ça c'est pas un pb....je vais essayer ta méthode...

    quand je dis rs virtuel , c'était plus tôt du genre :

    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
    Private Sub Class_Initialize()
    Dim lerep, sListeFic, laligne As String
    Dim i, nbFile As Integer
    Dim Fic
    Dim f1
    Dim lgSession
    Dim lgFtp As Long
    Dim inRes
    Dim sNomFic As String
     
     
        Set rsFichiers = New ADODB.Recordset ' Définit la variable d'objet.
     
        With rsFichiers
            .Fields.Append "NumCompte", adBSTR, 11
            .Fields.Append "Titulaire", adBSTR, 38
            .Fields.Append "Bureau", adBSTR, 5
            .CursorType = adOpenStatic
            .LockType = adLockOptimistic
            .Open
        End With
     
    End Sub
     
     
    Public Property Get RecordCount() As Long
       RecordCount = rsFichiers.RecordCount
    End Sub
     
    Public Sub Refresh()
       Call Class_Initialize
    End Sub
     
     
    ' alimente le tableau
    Private Sub P_alimRow(rs As ADODB.Recordset, lNumCompte As String, lTitulaire As String, lBureau As String)
        rs.AddNew
        rs!NumCompte = lNumCompte
        rs!Titulaire = lTitulaire
        rs!Bureau = lBureau
        rs.Update
    End Sub
     
    Public Sub P_alimRS(lefichier As String)
    Dim LefichierSource
    Dim laligne
     
        Set fs = CreateObject("Scripting.FileSystemObject")
     
        Set LefichierSource = fs.openTextFile(lefichier)
     
        Do While Not LefichierSource.AtEndOfStream
            laligne = LefichierSource.readline
            Call P_alimRow(rsFichiers, Mid(laligne, 1, 11), Mid(laligne, 12, 38), Mid(laligne, 50, 5))
        Loop
     
        If rsFichiers.RecordCount > 0 Then
            rsFichiers.MoveFirst ' Se place au début du jeu d'enregistrements.
        End If
     
        Set fs = Nothing
     
    End Sub

  5. #5
    Membre éclairé Avatar de sozie9372
    Inscrit en
    Mai 2005
    Messages
    713
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Mai 2005
    Messages : 713
    Points : 724
    Points
    724
    Par défaut
    ah oui en effet, tu allouais un objet et tu stockais tout dedans pour pouvoir l'exploiter par la suite... Merci pour le code (c'est plus facile a comprendre avec !)
    Tiens moi au courant.
    Je sais que le delimiteur est le ";" pour les fichiers csv, si tu trouve comment en utiliser d'autres, j'aimerais bien être informé
    +++
    Ju
    "Il y a 3 personnes en ce monde sur qui tu peux compter : moi, le pape et le cavalier solitaire ! "
    Penser à svp

  6. #6
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    49
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 49
    Points : 29
    Points
    29
    Par défaut
    la formule marche.....mais j'ai tout de même 22 secondes d'attente pour le résultat....m'enfin sur 1 600 000 lignes c'est pas trop mal. 8)

    Par contre bizarrement les le rs.next qui prend du temp et pas le open de la requête..comme ça se fait ? :

  7. #7
    Expert confirmé
    Avatar de zazaraignée
    Profil pro
    Étudiant
    Inscrit en
    Février 2004
    Messages
    3 174
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2004
    Messages : 3 174
    Points : 4 085
    Points
    4 085
    Par défaut
    Salut

    Ton fichier est-il enregistré en format Texte (.txt ou autre), donc lisible dans un éditeur de texte ou est-il enregistré en binaire (avec des champs de données déterminés)?

    Si ton fichier est binaire, il est facile de procéder avec une recherche dichotomique plutôt que par une recherche champ par champ. Il faut que ton fichier soit en ordre cependant (trié je veux dire).

  8. #8
    Expert confirmé
    Avatar de zazaraignée
    Profil pro
    Étudiant
    Inscrit en
    Février 2004
    Messages
    3 174
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2004
    Messages : 3 174
    Points : 4 085
    Points
    4 085
    Par défaut
    Salut, c'est encore moi.

    Je viens de me rendre compte que ton titre mentionne "fichier texte volumineux". Et comme les fichiers textes sont en accès séquentiels... mon astuce ne peut fonctionner... sauf si tu lis une première fois ton fichier pour le placer dans un tableau... que tu réenregistre après avoir fait tes modifications...

    Pour la recherche dichotomique (sur des tableaux), j'ai trouvé ce tutoriel sur développez. Il y en a d'autres. Fais une recherche sur Google avec les mots "algorithme recherche dichotomique". Ils sont une demi-douzaine.

  9. #9
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    49
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 49
    Points : 29
    Points
    29
    Par défaut
    Merci beaucoup , j'ai déjà penser à la recherche dicotomique le problème est qu'en le chargeant dans un tableau , ça va revenir sensiblement au même que dans mon cas de départ où je le stockais dans un recordset virtuel et donc mettre un temps assez phénoménal a être chargé( 4 à 5 minutes) et bouffer à max de ressources...(mon fichier de 1600 000 lignes représente environ 90 Mo et l'appli au moment ou elle le charge s'alloue au maximum 290 Mo de mémoire).. je pense qu'avec un tableau il en sera de même...

    La question que je me sui posé avec la méthode de sozie ,c'est :

    imaginons que je rajoute un index numérique incrémentale comme premier champs de mes lignes...est-ce qu'il ne serait pas plus rapide de ne récupérer dans un deuxième recordset que les index des lignes matchées (donc de mon premier recordset) par ma requête SQL et ensuite reparcourir le premier recordset avec une requête dont le where ne porte que sur l'index....

    c'est compliqué ce que je dis non ?? quelqu'un a compris ?

  10. #10
    Expert confirmé
    Avatar de zazaraignée
    Profil pro
    Étudiant
    Inscrit en
    Février 2004
    Messages
    3 174
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2004
    Messages : 3 174
    Points : 4 085
    Points
    4 085
    Par défaut
    Salut

    Le problème, c'est de faire pointer sur le bon enregistrement.

    Pourquoi ne pas enregistrer ton fichier texte en binaire? Ou en faire une copie binaire et faire une recherche dans la copie binaire?

  11. #11
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    49
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 49
    Points : 29
    Points
    29
    Par défaut
    = >> sozie9372

    j'ai un petit soucis avec le code que tu m'as passé .
    Pourquoi ne puis pas mettre autre chose que : "monfichier#txt" dans la requête SQL ...
    et pourquoi dès qu'on change le répertoire app.path par un autre cela ne fonctionne plus ? :

  12. #12
    Membre éclairé Avatar de sozie9372
    Inscrit en
    Mai 2005
    Messages
    713
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Mai 2005
    Messages : 713
    Points : 724
    Points
    724
    Par défaut
    Salut !

    Je ne sais pas pourquoi, mais ca doit être le format pour exécuter la requête, le fichier doit être, dans la requête, sous la forme "Select * from [monfichier#txt]"... Encore un truc magique de VB
    Pour ce qui concerne le chemin, normalement, c'est le chemin vers le dossier contenant les fichiers de données. Si ton fichier monfichier.txt est dans "C:\MesFichiersTextes\", alors le chemin lors de l'ouverture de la connexion sera "C:\MesFichiersTextes\".
    Petit exemple :

    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
     
    '------------------------------------------------- 
    ' le fichier "monFichier.txt" est dans le répertoire "C:\MesFichiersTextes\".
    Public Sub test() 
       Dim rs As ADODB.Recordset 
       Dim query As String 
       open_connection "C:\MesFichiersTextes\"
       query = "SELECT * FROM [monFichier#txt] WHERE CHAMP1='MAVALEUR13'" 
       Set rs = execQuery query 
       While Not rs.EOF 
           Debug.print "résultat : " & rs.Fields(0) & " " & rs.Fields(1) 
           rs.moveNext 
       Wend 
       close_connection 
    End Sub
    Normalement ca devrait fonctionner...
    J'espère avoir répondu à tes questions.
    +++
    Ju
    "Il y a 3 personnes en ce monde sur qui tu peux compter : moi, le pape et le cavalier solitaire ! "
    Penser à svp

  13. #13
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    49
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 49
    Points : 29
    Points
    29
    Par défaut
    j'ai écrit cela en dur dans mon prog :

    open_connection "c:\Test\Entree\"
    et bien avec "monfichier.txt" dans c:\Test\Entree ...ça ne fonctionne pas... dès que je relmets open_connection app.path avec le même "monfichier.txt" dans le rep de mon vbp ....ça fonctionne

    et pour [monfichier#txt] idem...si je lui met [test1#txt] parce que mon fichier s'appelle teste1.txt ....ne fonctionne pas non plus.
    Me dis pas qu'il faut figer le nom du fichier à monfichier.txt et le placer obligatoirement dans le app.path ?

  14. #14
    Membre éclairé Avatar de sozie9372
    Inscrit en
    Mai 2005
    Messages
    713
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Mai 2005
    Messages : 713
    Points : 724
    Points
    724
    Par défaut
    Salut !

    Je viens de faire le test, et ca fonctionne...
    J'ai mis mon fichier "test1.txt" dans le repertoire "C:\Tests\MesEntrees\" et j'ai modifié le Sub test comme suit :
    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
     
    '-------------------------------------------------
    ' le fichier "monFichier.txt" est dans le répertoire de l'application
    Public Sub test()
       Dim rs As ADODB.Recordset
       Dim query As String
       open_connection "C:\Tests\MesEntrees\"
       query = "SELECT * FROM [test1#txt] WHERE MONCHAMP1='MAVALEUR13'"        ' Bon ici c'est MONCHAMP1 au lieu de CHAMP1
       Set rs = execQuery(query)
       While Not rs.EOF
           Debug.Print "résultat : " & rs.Fields(0) & " " & rs.Fields(1)
           rs.moveNext
       Wend
       close_connection
    End Sub
    J'avais juste un problème de champs, dans la requete, c'est MONCHAMP1 et non pas CHAMP1 si je reprend le premier exemple de fichier csv que je t'ai donné.
    Résultat :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    résultat : MAVALEUR13 MAVALEUR23
    Tu dis que ca ne marche pas, mais qu'est-ce qui ne marche pas ? T'as une erreur, ca fait rien du tout ou au contraire ca fait quelquechose de pas bon ?
    Tiens moi au courant
    +++
    Ju
    "Il y a 3 personnes en ce monde sur qui tu peux compter : moi, le pape et le cavalier solitaire ! "
    Penser à svp

  15. #15
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    49
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 49
    Points : 29
    Points
    29
    Par défaut
    en faite, c'est hallucinant..
    car que je change le nom de "monfichier.txt" ou que je change le path...

    et bien j'ai pas une erreur , c'est au moment de l'éxécution de la query :

    rs.Open query, Cnx , que ça dure 30 secondes....

    tout ça pour me rendre un rs.recordcount = -1................... alors que la requête n'a pas changé que la Cnx est bien bonne...

    quand tout fonctionne normalement , l'éxécution de la query est quasi instantané et c'est au moment de boucler sur le detail du recordset qu'il prend du temps , mais vula volumétrie je pense que c'est normal...

    Reedition : en faite , je crois que je viens de trouver....rien à voir avec nom des fichiers ou du path.....il y avait des conflits entre les décalrations de mes "rs"....

  16. #16
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    49
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 49
    Points : 29
    Points
    29
    Par défaut
    je reveiens une dernière fois àla charge avec ça..

    Mais je viens de m'appercevoir en faite que le recordset me retourne des valeurs "dépouillées de leur 0")
    Dans ma première colonne , j'ai des numéro de compte du genre
    "00000124567" et le recordset me renvoie "124567"....comment lui spécifier une récupération en mode texte... :

  17. #17
    Membre éclairé Avatar de sozie9372
    Inscrit en
    Mai 2005
    Messages
    713
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Mai 2005
    Messages : 713
    Points : 724
    Points
    724
    Par défaut
    Salut !

    Je suis désolé, mais là ca dépasse mes compétences, si tes valeurs font toutes la même taille, tu peux compléter avec des 0, sinon je n'ai pas d'autre idée à part trouver la commande permettant de spécifier le type de données souhaité...

    Désolé. Demande peut-être aux SQLMans ils doivent avoir une solution là dessus.
    +++
    Ju
    "Il y a 3 personnes en ce monde sur qui tu peux compter : moi, le pape et le cavalier solitaire ! "
    Penser à svp

  18. #18
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    49
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 49
    Points : 29
    Points
    29
    Par défaut
    en faite j'ai trouvé ...

    j'ai rajouté des guillemets dans mon fichier texte.

    "Champs1";"champs2";"champs3"......et là la récupération dans le recordset se fait au format texte.

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

Discussions similaires

  1. [EasyPHP] recherche dans un fichier texte
    Par cflo91 dans le forum EDI, CMS, Outils, Scripts et API
    Réponses: 19
    Dernier message: 03/07/2007, 15h33
  2. Recherche dans un fichier texte
    Par Yazoo70 dans le forum C++
    Réponses: 7
    Dernier message: 12/06/2007, 08h31
  3. recherche dans un fichier texte en perl(débutant)
    Par Shyboy dans le forum Langage
    Réponses: 3
    Dernier message: 04/07/2006, 23h53
  4. [VB]Recherche dans un fichier texte
    Par mirascheat dans le forum VB 6 et antérieur
    Réponses: 1
    Dernier message: 26/09/2005, 12h11
  5. [LG]rechercher dans un fichier texte
    Par BadFox dans le forum Langage
    Réponses: 11
    Dernier message: 01/12/2003, 15h57

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