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

C++ Discussion :

[Fichiers] Lire une ligne spécifique dans un (gros) csv


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Inscrit en
    Septembre 2006
    Messages
    113
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 113
    Par défaut [Fichiers] Lire une ligne spécifique dans un (gros) csv
    Bonjour,

    j'ai un fichier de paramètres dépendant du temps pour un programme qui est sous format CSV.
    Ce fichier se présente sous la forme suivante:

    Colonnes:
    la variable temporelle en colonne. Il ya 480 mois (40 ans) => 480 colonnes



    Lignes:
    PLus de 1000 lignes. Chacune de ces lignes correspond à une simulation bien précise. Ces lignes sont ordonnées (plus petite simul vers la plus grande)
    La première colonne reprend le numéro de la simulation.


    J'aimerais faire qqch du style:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    int lastSimulation = 1000;
    for (int i = 1; i<= lastSimulation; i++){
        std::ifstream fichier( "fichier.txt" );
     
        if ( fichier ) 
        {
            std::string ligne; 
            while ( std::getline( fichier, ligne ) ) {
                   if( on est sur la ligne correspondant au compteur i)
                         doSomething();        
             }
         }
    }
    Le code (que j'ai retapé de mémoire ) fonctionne, mais le problème est que si le n° de simulation est dans le début du fichier, j'arrive à la fonction doSomething() (forcément) assez vite, par contre si la simulation est très loin dans le fichier, ca prend bcp de temps (une seconde contre qqs millisecondes).
    Le temps étant très important pour moi, avez vous une idée pour acceder à une ligne particulière plus rapidement?

    Merci bcp
    David

  2. #2
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Par défaut
    Je ne sais pas si c'est possible mais si les lignes font toutes la même longueur, tu pourrais utiliser fseek (ou équivalent) afin de te positionner directement dans le fichier sur la ligne à lire. Par contre, attention si une seule ligne ne respecte pas le format !!!

    Si le critère de temps de positionnement est vraiment important, tu pourrais même imposer une taille fixe pour tes lignes.

    C'est le seul moyen que je voie pour optimiser le temps d'accès à une ligne particulière.
    Raymond
    Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi

    Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
    e-verbe Un logiciel de conjugaison des verbes de la langue française.

    Ma page personnelle sur DVP
    .

  3. #3
    Membre confirmé
    Inscrit en
    Septembre 2006
    Messages
    113
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 113
    Par défaut
    En fait toutes les colonnes contiennent des chiffres (hormis la première qui indique le n0 de la simulation (c'est aussi un chiffre :-) ).
    Ces chiffres sont du style 0.0457568 mais avec parfois moins ou plus de décimales... Et il n'est pas possible de restreindre la taille pcq c'est un autre programme (un générateur de scénarios économiques) qui me fournit cet input sous format csv.

  4. #4
    Membre éclairé
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Octobre 2005
    Messages
    244
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Philippines

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Octobre 2005
    Messages : 244
    Par défaut
    A) D'un coté:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
        std::ifstream fichier( "fichier.txt" );
     
        if ( fichier ) 
        {
     
            std::string ligne; 
            int i = 0;
            while (  std::getline( fichier, ligne ) && (i++<lastSimulation) ) {
                   if( on est sur la ligne correspondant au compteur i) //Renverra toujours vrai
                         doSomething();        
             }
         }
    ça ne sert à rien de double boucler!

    B) Sinon tu peux pas tous passer en memoire?

    Si A et B ne conviennents pas:

    C) Algorithme recursif en complexité log2:

    fonction chercher_log2(int commencerOu)

    fseek(commencerOu)

    lire jusqu'au prochain caractere "\n" (saut de ligne, ou fin de fichier)

    if( on est sur une ligne inferieur au compteur i)
    alors
    -> chercher_log2(commencerOu + commencerOu/2)
    sinon
    if(on est sur une ligne egale au compteur i)
    retourner ligne ou flux ou directement la structure etc...
    sinon
    -> chercher_log2(commencerOu - commencerOu/2)
    fin if
    fin if
    Cela marche uniquement si toute tes structures sont dans un ordre triée

  5. #5
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,

    Peut-être - étant donné que tu as un nombre de colonnes connues - serait-il intéressant d'envisager un simili fichier ISAM (le I étant pour "indexed" )

    Dans un fichier à part, tu indiques les offsets de chaque début de ligne, et tu charges ces offset dans un tableau en début de programme.

    Quand tu dois accéder à un élément X, tu calcule pos = X / nombre_colonnes à l'arrondi inférieur, et tu récupères l'offset en tab_offset[pos].

    Cet offset te permet (à l'aide de fseek) de sauter directement au début de ligne qui t'intéresse, et tu n'a plus au maximum qu'à lire la totalité des colonnes de cette ligne

    Nous ne sommes pas encore en O(log(n)), cela te permet de garder un temps "presque constant" (constant pour aller chercher la ligne, en O(N) pour aller chercher la colonne)

    Pour obtenir l'index, l'idéal serait de modifier l'application qui crée ton fichier CSV de manière à ce qu'elle crée l'index, mais, sinon:
    1. tu peux créer une petite application qui s'en charge (ca doit pas faire beaucoup plus de 5 lignes )
    2. Tu peux lire une fois le fichier au lancement de ton application, et créer l'index "à la volée" (ici aussi, cela ne fait pas beaucoup plus de 5 lignes )
    Cependant, ces deux dernières solutions seront plus lentes que la solution idéale

    [EDIT]Il est aussi possible de prévoir un index d'offset toutes les X données (ou X peut varier à ton gré de 1 - qui n'est pas vraiment intéressant au vu de la taille du tableau qu'il implique - à autant que tu veux )
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  6. #6
    Membre confirmé
    Inscrit en
    Septembre 2006
    Messages
    113
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 113
    Par défaut
    Mais il ya une sorte d'index, puisque la première colonne contient le n° de la simulation..

    On a qqch du style:
    Simul ; 0 ; 1 ; 2 ; 3 ;......
    1; 0.045 ; 0.0645; 0.0368; 0.12 ;....
    2; 0.0756; 0.0752; 0.0953; 0.564 ;....
    3; 0.065 ; 0.0123; 0.0321; 0.8525;....
    ......

    Est ce que je peux l'utiliser astucieusement?

  7. #7
    Membre confirmé
    Inscrit en
    Septembre 2006
    Messages
    113
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 113
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Salut,

    Peut-être - étant donné que tu as un nombre de colonnes connues - serait-il intéressant d'envisager un simili fichier ISAM (le I étant pour "indexed" )

    Dans un fichier à part, tu indiques les offsets de chaque début de ligne, et tu charges ces offset dans un tableau en début de programme.

    Quand tu dois accéder à un élément X, tu calcule pos = X / nombre_colonnes à l'arrondi inférieur, et tu récupères l'offset en tab_offset[pos].

    Cet offset te permet (à l'aide de fseek) de sauter directement au début de ligne qui t'intéresse, et tu n'a plus au maximum qu'à lire la totalité des colonnes de cette ligne

    Nous ne sommes pas encore en O(log(n)), cela te permet de garder un temps "presque constant" (constant pour aller chercher la ligne, en O(N) pour aller chercher la colonne)

    Pour obtenir l'index, l'idéal serait de modifier l'application qui crée ton fichier CSV de manière à ce qu'elle crée l'index, mais, sinon:
    1. tu peux créer une petite application qui s'en charge (ca doit pas faire beaucoup plus de 5 lignes )
    2. Tu peux lire une fois le fichier au lancement de ton application, et créer l'index "à la volée" (ici aussi, cela ne fait pas beaucoup plus de 5 lignes )
    Cependant, ces deux dernières solutions seront plus lentes que la solution idéale

    [EDIT]Il est aussi possible de prévoir un index d'offset toutes les X données (ou X peut varier à ton gré de 1 - qui n'est pas vraiment intéressant au vu de la taille du tableau qu'il implique - à autant que tu veux )


    Bonjour
    J'ai essayé cette solution, càd que je crée un petit fichier txt qui indique à chaque ligne l'offset correspondant à la longueur de la ligne correspondante dans mon fichier de base.

    Ensuite, lorsque j'ai besoin d'une ligne en particulier, j'ouvre mes deux fichiers (le gros et le petit) et je recupère dans le petit l'offset correspondant à ma simulation et je me déplace à l'aide de fseek dans le gros fichier jusque l'offset et je récupère ma ligne.
    Tout fonctionne bien, sauf qu'au niveau du temps c'est pas top.

    Lorsque je fais tourner mon programme sur les 100 premieres simulations , ça prend 1 minute (c'est le temps que dure mon programme => il faut prendre le temps relatif)
    Lorsque je fais tourner mon programme sur les 100 premieres simulations , ca prend 5 minutes

    => j'ai (en gros) un rapport X5 entre le fait d'accèder aux premières lignes et les dernières lignes...

    C'est un peu genant car je voudrais réduire le temps de calcul considérablement...:-/

    Si vous avez une idée...
    Merci

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

Discussions similaires

  1. [WM17] Lire une ligne spécifique d'un fichier.
    Par Papach58 dans le forum Windev Mobile
    Réponses: 3
    Dernier message: 11/03/2014, 23h42
  2. Lire une ligne précise dans un fichier de données
    Par IcArnus dans le forum Débuter
    Réponses: 7
    Dernier message: 05/04/2012, 22h25
  3. [Débutant] Lire une ligne spécifique depuis un fichier
    Par Sperafico dans le forum VB.NET
    Réponses: 7
    Dernier message: 27/01/2012, 13h00
  4. Lire une ligne spécifique dans un fichier texte
    Par ZRemi dans le forum MATLAB
    Réponses: 2
    Dernier message: 26/04/2010, 13h58
  5. Lire une ligne précise dans un tableau
    Par kenru dans le forum PHP & Base de données
    Réponses: 3
    Dernier message: 23/12/2009, 14h08

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