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 :

Parsing fichier CSV


Sujet :

C++

  1. #1
    Membre régulier
    Inscrit en
    Mai 2006
    Messages
    330
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 330
    Points : 85
    Points
    85
    Par défaut Parsing fichier CSV
    Salut,

    J'ai un tableau excel (format CSV - champs séparés par des ";") à parser.

    Y aurait-il une méthode plus rapide que de lire chaque ligne (avec std::getline()) et d'en extraire les champs en cherchant leurs positions de départ et de fin (avec string::find_first_of()) puis en extrayant une sous-chaine de la ligne (avec string::substr()) ?

    Merci

  2. #2
    Membre éprouvé
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 064
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 064
    Points : 1 053
    Points
    1 053
    Par défaut
    Ben ça dépend. Faudrait déjà que tu nous montres un morceau de fichier csv comme exemple (excuse nous, tout le monde ne connait pas par cœur la syntaxe de tous les fichiers office, crois le ou non tout le monde n'utilise même pas office) ainsi que ton code, on pourra alors faire apparaitre d'éventuels problèmes d'optimisation.
    Dans l'absolu, une bonne méthode pour analyser un texte rapidement est tout simplement d'utiliser les techniques ancestrales mises au point il y a des années dans ce but, bref tout ce qui se rapporte à la compilation. Il y a quelques tutos bien foutus sur le site qui en parlent (cherche dans la partie algorithmique). Normalement pour un truc aussi simple un petit analyseur lexical avec un peu de bricolage par dessus (pour pas avoir à se taper un analyseur syntaxique complet) serait ce qui se fait de mieux. En plus quand on a fait un lexer on les a tous faits, et ça a toujours son utilité, alors ce n'est pas de l'effort d'apprentissage dépensé pour rien.

  3. #3
    Membre régulier
    Inscrit en
    Mai 2006
    Messages
    330
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 330
    Points : 85
    Points
    85
    Par défaut
    Citation Envoyé par zais_ethael Voir le message
    Ben ça dépend. Faudrait déjà que tu nous montres un morceau de fichier csv comme exemple
    Ben c'est très simple, si mon tableau excel est constitué de 3 lignes et 2 colonnes le fichier CSV est de style :

    valeur(1, 1);valeur(1,2) retour à la ligne
    valeur(2, 1);valeur(2,2) retour à la ligne
    valeur(3, 1);valeur(3,2) retour à la ligne

    où valeur(i, j) est la valeur de la cellule à la ligne i et la colonne j.

  4. #4
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 629
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 629
    Points : 30 692
    Points
    30 692
    Par défaut
    Salut,

    En fait, tout dépendra sans doute du type des valeurs de tes différentes colonnes/lignes, ainsi que de ta (ton in)certitude que toutes les lignes et toutes les colonnes sont bien remplies, et, enfin, de l'éventuelle présence de cellules dans lesquelles il y aurait des résultats calculés (totaux et autres).

    Si tu as la certitude que toutes les cellules attendues sont correctement remplies, tu peux envisager de lire directement les informations du type attendu pour chaque cellule, mais cela signifie courir le risque que ton fichier ait été corrompu, avec à la clé certaines incohérences potentielles au niveau des données lues.

    Ainsi, le code suivant va créer un fichier cvs ressemblant aux informations que tu as fournie, mais uniquement sous la forme de valeur entières puis le relire et placer dans un tableau de tableaux d'entier, pour enfin les réafficher.
    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
     
    #include <iostream>
    #include <fstream>
    #include <vector>
    using namespace std;
    /* fonction de création du fichier cvs
     * s'assurant que toutes les lignes de toutes les colonnes sont remplies
     */
    void createCVS()
    {
        ofstream ofs("essai.cvs");
        for(size_t i=0;i<10;i++)
        {
            for(size_t j=0;j<10;j++)
            {
                    ofs<<i*10+j;
                    if(j==9)
                        ofs<<endl;
                    else
                        ofs<<" ; ";
            }
        }
    }
    /* fonction delecture du fichier cvs précédemment créé 
     */
    void readCVS(vector< vector<size_t> >& tab)
    {
        ifstream ifs("essai.cvs");
        for(size_t i=0;i<10; i++)
        {
            vector<size_t> ligne;
            for(size_t j=0;j<10;j++)
            {
                char space;
                size_t entier;
                ifs>>entier;
                ligne.push_back(entier);
                if(j<9)
                    ifs>>space;
            }
            tab.push_back(ligne);
        }
    }
    int main()
    {
        vector< vector<size_t> > tab;
        createCVS();
        readCVS(tab);
        /* affichage des informations récupérées 
         */
        for(vector<vector< size_t> >::const_iterator it=tab.begin();
            it!=tab.end();it++)
        {
            for(size_t cpt=0;cpt< (*it).size();cpt++)
                cout<<(*it)[cpt]<<" ";
            cout<<endl;
        }
        return 0;
    }
    Comme on peut être sur que toutes les cellules et toutes les colonnes sont correctement remplies, et qu'il n'y aura donc aucun problème, on peut éviter toutes les vérifications fastidieuses de cohérence du fichier

    S'il y avait eu des types de données différents dans les colonnes, nous aurions très bien pu envisager de créer une classe qui aurait contenu les différentes données, et d'utiliser seulement un tableau du type de cette classe...

    Par contre, s'il n'y a ne serait-ce qu'un seul risque pour qu'une colonne n'existe pas - ou qu'une colonne supplémentaire fasse son apparition, ou que le fichier soit corrompu, voire, tout simplement, que le ";" arrive directement après le dernier caractère réel de la chaine, ou qu'une chaine soit entourée de guillemets - alors, tu devra commencer à mettre certains mécanismes plus complexes en œuvre pour récupérer tes données

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

    Informations forums :
    Inscription : Juin 2006
    Messages : 107
    Points : 122
    Points
    122
    Par défaut
    je te conseille de ne pas perdre ton temps à parser toi-même un fichier CSV (il y a des pièges), mais d'utiliser une lib :
    http://sourceforge.net/projects/libcsv/

  6. #6
    Membre régulier
    Inscrit en
    Mai 2006
    Messages
    330
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 330
    Points : 85
    Points
    85
    Par défaut
    Citation Envoyé par koala01 Voir le message
    ...
    Oui, en fait ça ne convint pas tout à fait car je ne connais pas le type (chaine, entier, flottant) d'une cellule et en plus il peut y avoir des trous dans le tableau.

  7. #7
    Membre régulier
    Inscrit en
    Mai 2006
    Messages
    330
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 330
    Points : 85
    Points
    85
    Par défaut
    Citation Envoyé par lemmel Voir le message
    je te conseille de ne pas perdre ton temps à parser toi-même un fichier CSV (il y a des pièges), mais d'utiliser une lib :
    http://sourceforge.net/projects/libcsv/
    Je vais jter un oeil, mais y a t-il une bonne raion que ça aille plus vite que de parser soi-même ? car le code je l'ai déjà écrit et ça marche bien...c'est juste que j'aimerais qu'il soit plus rapide.

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

    Informations forums :
    Inscription : Juin 2006
    Messages : 107
    Points : 122
    Points
    122
    Par défaut
    as-tu pensé au fait que
    - un vrai CSV (i.e. exporté depuis excel), peut encadrer les champs par des " ?
    - un champs peut être multiligne
    - lorsque qu'un " figure dans un champs protégé celui-ci est doublé ?
    - le séparateur peut être ; mais aussi , ?

    au final tu va refaire le travail déjà fourni par la lib conseillé, mais en moins bien (je l'utilise et je parse des Mo de données en un rien de temps).

  9. #9
    Membre éprouvé
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 064
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 064
    Points : 1 053
    Points
    1 053
    Par défaut
    Citation Envoyé par tnarol Voir le message
    Je vais jter un oeil, mais y a t-il une bonne raion que ça aille plus vite que de parser soi-même ? car le code je l'ai déjà écrit et ça marche bien...c'est juste que j'aimerais qu'il soit plus rapide.
    En dehors des problèmes que lemmel a soulevé, et dans une optique purement optimisation, oui. Les méthodes fournies par std::string sont pratiques et probablement faciles à utiliser, mais elles ne remplacent pas un lexer fait dans les règles de l'art, ce qui est ce qui se fait de plus rapide par son principe même (les expressions régulières).
    Par exemple, dans ton algo, à moins de l'avoir briqué à fond, il est possible que tu fasses plusieurs parcours d'une chaine alors qu'un seul est suffisant, ou que tu fasses trop d'allocations mémoire (ça arrive vite avec std::string, c'est un inconvénient).
    En même temps, je doute fort que l'optimisation soit d'une importance capitale dans un cas pareil, tu n'arriveras jamais à avoir plusieurs milliers de lignes (et si c'est le cas, il faudrait peut-être penser à stocker tes infos dans une bd plutot que dans des fichiers excel). Les problèmes soulevés par lemmel sont plus importants.
    PS: analyse lexicale != analyse syntaxique (parsing), dans ce cas le parsing est quasiment inexistant.

Discussions similaires

  1. NullPointerExecption lors du parsing d'un fichier csv
    Par RTK45 dans le forum Entrée/Sortie
    Réponses: 3
    Dernier message: 27/04/2013, 19h58
  2. Parse du fichier CSV : Optimisation Vs. Nombres de lignes
    Par aelmalki dans le forum Général Java
    Réponses: 4
    Dernier message: 04/03/2011, 13h31
  3. [RegEx] Parsing de fichier csv
    Par Khamsin dans le forum Langage
    Réponses: 2
    Dernier message: 10/02/2011, 12h13
  4. Mise à jour d'une table avec un fichier csv
    Par blackangel dans le forum PostgreSQL
    Réponses: 4
    Dernier message: 26/05/2005, 14h46
  5. Réponses: 2
    Dernier message: 14/05/2004, 12h55

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