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 Perl Discussion :

Bonne méthode pour lire un fichier volumineux ?


Sujet :

Langage Perl

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    43
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 43
    Points : 42
    Points
    42
    Par défaut Bonne méthode pour lire un fichier volumineux ?
    bonjour,
    Je suis en train de faire un script en perl pour découper un fichier xml et je suis confronté à un temps de traitements plutôt long sur des fichiers volumineux, plus d'une minutes pour un fichier de 60Mo. (je suis sur un système unix)

    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
    if (not open(FICIN,"< $nomFicXml") ) {
    	return -1;
    }
     
     
    while ( $ligne = <FICIN> ) 
    {
     
    	if($ligne =~ $baliseDebut)		
    	{
    		//traitement
     
    	}
     
    }
    J'aurai voulus savoir si il y a des techniques pour réduire ce temps

  2. #2
    Responsable Perl et Outils

    Avatar de djibril
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    19 820
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 19 820
    Points : 498 771
    Points
    498 771
    Par défaut
    La lecture de fichiers est optimisée via une lecture ligne à ligne. Tu ne peux pas faire mieux. (Du moins, il est possible octet par octet, mais ça n'aurais pas de sens). Cela évite de charger tout le fichier en mémoire.
    Maintenant tout dépend du nombre de lignes, du traitement effectué sur chaque ligne, de ta machine, type de disque, vitesse de lecture des disques, processeurs, etc

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    43
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 43
    Points : 42
    Points
    42
    Par défaut
    Les tests que je fait sont sur un fichier de 3 220 659 lignes, es ce que en passant par un autre langage je pourrais diminuer mon temps de traitements,
    sachant que lorsque je fait un 'grep -be monMotif monFichier' il me donne le résultat en à peine 10secondes (c'est deux fois moins le temps que met mon programme perl lorsque je fait que parcourir le fichier sans rien faire)

  4. #4
    Responsable Perl et Outils

    Avatar de djibril
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    19 820
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 19 820
    Points : 498 771
    Points
    498 771
    Par défaut
    j'ai crée un fichier de 3 220 659 lignes qui fait 125 Mo en à peine 3 secondes.
    J'ai effectué la lecture de ce fichier sans rien faire en moins d'une seconde :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     #!/usr/bin/perl
    use warnings;
    use strict;
     
    open my $fh, '<', 'test.txt';
    while ( <$fh> ) {
     
    }
    close $fh;
    En rajoutant un test
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    if ( /test/ ) { 
        # ...
       }
    Il ne met pas plus de temps.

    Donc bon, est ce ton code qui pose souci ?

    Je rajouterais également que la manipulation de fichier XML n'est pas adaptée via de simples regex, il faudrait nous en dire plus sur ce que tu souhaites faire pour t'orienter vers de bonnes solutions.

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    43
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 43
    Points : 42
    Points
    42
    Par défaut
    Merci djibril pour les test que tu as fait, je viens de faire les même tests que toi
    avec ton script et j'arrive à 14 secondes sans rien faire et 21 seconde avec un test. Donc, déjà la machine ou j'exécute le perl est moins performante.
    Le but de mon programme est de récupérer un ensemble de bloc en fonction que le bloc contienne une chaîne rechercher.
    Exemple de fichier xml :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    <PRODUIT>
    <LIB>ab</LIB>  
    ...
    </PRODUIT>
    <PRODUIT>
    <LIB>abcd</LIB>  
    ...
    </PRODUIT>
    en sortie je voudrais avoir que le bloc qui contient la balise <LIB>ab</LIB>

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    <PRODUIT>
    <LIB>ab</LIB>  
    ...
    </PRODUIT>

  6. #6
    Responsable Perl et Outils

    Avatar de djibril
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    19 820
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 19 820
    Points : 498 771
    Points
    498 771
    Par défaut
    XML::Twig sera ton ami.

    Peux tu nous mettre un exemple plus complet de ton XML et du fichier résultat que tu souhaites obtenir.

  7. #7
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    43
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 43
    Points : 42
    Points
    42
    Par défaut
    Dans mon fichier xml, un bloc a environs 1200 lignes

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    <BLOC>
    bloc1
    <BLOC/>
    <BLOC>
    bloc n
    <BLOC/>
    Si j'utilise le module que tu cite, je risque d'avoir des temps de traitements encore plus long non?

  8. #8
    Responsable Perl et Outils

    Avatar de djibril
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    19 820
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 19 820
    Points : 498 771
    Points
    498 771
    Par défaut
    Si tu souhaites avoir de l'aide, met moi un fichier XML que je peux pendre en exemple pour tester un programme dessus. Je n'ai pas le temps de me prendre la tête à concevoir un fichier XML sans savoir à quoi il doit ressembler. De plus, un fichier de sortie voulu sera également bien. Je ne te demande pas de mettre un fichier de 1000 lignes, mais au moins un fichier d'une vingtaine de lignes serait plus clair.

    Ensuite, Je te conseil ce module car du moment où tu souhaites parser un fichier balisé, notamment un XML, il est plus propre et correct d'utiliser un module adéquat sous peine de rencontrer des soucis via les regex pour des XML plus complexes.

    Les conseils ci-dessus sont de mon point de vu déjà plus important que la performance du programme. Ensuite, les parseurs XML sont prévus pour gérer ce genre de fichiers, étant donné qu'il existe de très nombreux fichiers XML très volumineux dans la nature. Après il faut avoir un algorithme propre comme pour tout langage de programmation pour bien analyser son fichier.

    Voilà

  9. #9
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Points : 5 753
    Points
    5 753
    Par défaut
    Cela dit, il n'a pas tout à fait tord, car un type de parser DOM chargera en mémoire tout l'arbre XML, ce qui peut s'avérer problématique avec de gros arbres
    Dans ces cas là, un parser événementiel (type SAX) serait plus approprié. Cependant, la problématique soulevée par sth56 relève plutôt d'un parcours d'arbre que d'une recherche "à la volée".

  10. #10
    Responsable Perl et Outils

    Avatar de djibril
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    19 820
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 19 820
    Points : 498 771
    Points
    498 771
    Par défaut
    Mais quand je lui demande des exemples clairs, c'est pour adapter le programme avec une solution SAX qu'XML::Twig gère très bien si l'on ne souhaite pas charger tout fichier en mémoire .

  11. #11
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    43
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 43
    Points : 42
    Points
    42
    Par défaut
    Voila un exemple du fichier xml que je veux découper (Facture.xml) qui comprend trois blocs, en résultat j'ai deux blocs.

    Ma clef de recherche était une liste '<NUM>fact1</NUM>|<NUM>fact3</NUM>'.

    Quand j'aurai un peu plus de temps je regarderais comment faire fonctionner le module XML::Twig pour voir si en l'utilisant je gagne en performance et aussi si avec ce module je ne monopolise pas tous le cpu.
    Fichiers attachés Fichiers attachés

  12. #12
    Responsable Perl et Outils

    Avatar de djibril
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    19 820
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 19 820
    Points : 498 771
    Points
    498 771
    Par défaut
    Bon, je viens de regarder tes fichiers, mais j'aimerais quand même soulever quelques points :
    • Lorsque vous demandez de l'aide, essayez d'être précis car on perd énormément de temps à deviner vos besoins
    • Lorsque vous proposez des fichiers ou données, assurez vous que ces derniers soient dans un format lisibile


    Tes fichiers XML étaient vraiment illisibles, il a fallu que je les indente pour avoir un fichier potable et compréhensible .
    En comparant tes deux fichiers, voilà ce que j'ai compris : tes recherches se basent sur le contenu de la balise NUM. Ton fichier XML est architecturé de la sorte :
    Code xml : 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
      ....
    <FAC>
        <CORP>
          <INFCLI>
            <REFCLI>refCli3</REFCLI>
            <NOCPTE>compte3</NOCPTE>
            <CATCLI/>
            <VIPCODE/>
            <MODEPAIE/>
            <FREQFACT/>
            <CIVCLI/>
            <PRECLI/>
            <NOMCLI/>
            <ADR3/>
            <CP/>
            <VILLE/>
            <MAIL/>
            <DATECREA/>
          </INFCLI>
          <CLILIGNES>
            <NDI/>
            <NDI_TYPE/>
            <NDI/>
            <NDI_TYPE/>
            <NDI/>
            <NDI_TYPE/>
          </CLILIGNES>
          <INFFAC>
            <NUM>fact3</NUM>
    ....
    ....
    </FAC>
    Si tu ne souhaites pas garder fact3, il faut supprimer tout le bloc correspondant à la balise <FAC>. Pour être plus clair, tu ne gardes que les blocs FAC contenant ta clé de recherche dans la balise NUM et les autre blocs du même niveau que FAC (HDR, TRL, ...).

    D'où tout l'intérêt d'utiliser un vrai parser XML pour faire des traitements propres. Sinon tu cours à la catastrophe .

    Ai je bien saisie ta problématique ?

    NB : Un autre conseil, il faut arrêter de penser performance avant même de penser algorithme et surtout faisabilité d'un programme, projet, ça n'a pas de sens.

  13. #13
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    43
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 43
    Points : 42
    Points
    42
    Par défaut
    Oui djibril tu as bien résumé mon besoin, actuellement j'ai fait un programme en perl qui répond à mon besoin, le seul hic c'est que je le trouvais un peu long. Après faudra que je test avec un parser xml voir si c'est facile à utiliser et si j'ai un gain réel à utiliser cette méthode.

  14. #14
    Responsable Perl et Outils

    Avatar de djibril
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    19 820
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 19 820
    Points : 498 771
    Points
    498 771
    Par défaut
    Pour un fichier, il dure combien de temps ton programme ?
    Je vais essayer d'en faire un de mon coté si j'ai du temps.

    Je viens de faire ton programme, et il dure 1 seconde pour ton fichier facture.xml.

  15. #15
    Responsable Perl et Outils

    Avatar de djibril
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    19 820
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 19 820
    Points : 498 771
    Points
    498 771
    Par défaut
    Cadeau
    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
    #!/usr/bin/perl
    use Carp;
    use strict;
    use warnings;
     
    use XML::Twig;
    use File::Temp qw/ tempfile /;
     
    # Liste des cles à chercher
    my @motif = qw/ fact1 fact3 /;
     
    my %cles = map { $_ => 1 } @motif;
    my ( $fh_temp, $file_temp ) = tempfile( 'XXXX', UNLINK => 1 );
     
    my $twig = XML::Twig->new(
      twig_roots               => { 'FAC' => \&process_fac, },
      twig_print_outside_roots => $fh_temp, # print the rest
      PrettyPrint              => 'indented',
    );
    $twig->parsefile('Facture.xml');
    $twig->purge;
    close($fh_temp);
    rename( $file_temp, 'test.xml' );
     
    sub process_fac {
      my ( $twig, $twig_fac ) = @_;
      my $twig_corp = $twig_fac->first_child('CORP');
      if ( !defined $twig_corp ) { $twig_fac->purge; return; }
     
      my $twig_inffac = $twig_corp->first_child('INFFAC');
      if ( !defined $twig_inffac ) { $twig_fac->purge; return; }
     
      my $twig_num = $twig_inffac->first_child('NUM');
      if ( !defined $twig_num ) { $twig_fac->purge; return; }
     
      my $contenu_num = $twig_num->text;
      if ( $contenu_num and exists $cles{$contenu_num} ) {
        $twig_fac->print($fh_temp);
      }
      $twig_fac->purge;
      return;
    }

  16. #16
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    43
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 43
    Points : 42
    Points
    42
    Par défaut
    merci djibril pour le script, j'ai essayé ton script mais je reste bloqué sur une erreur, lorsque le script essaie de parser le fichier Facture.xml

    Couldn't open encmap iso-8859-15.enc:

  17. #17
    Responsable Perl et Outils

    Avatar de djibril
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    19 820
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 19 820
    Points : 498 771
    Points
    498 771
    Par défaut
    Tu as un souci d'encodage. Ton fichier XML n'est peut être pas au format iso-8859-15. Pour tester le programme, j'ai mis le XML au format utf-8 et ai changé l'entête par
    Code xml : Sélectionner tout - Visualiser dans une fenêtre à part
    <?xml version="1.0" encoding="utf-8"?>

  18. #18
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    43
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 43
    Points : 42
    Points
    42
    Par défaut
    Avec la modification de l'entête ça fonctionne très bien sur le fichier de trois bloc, le soucis c'est que le fichier que je doit découper est un fichier client donc pas modifiable, et en plus quand je test sur un fichier plus volumineux je récupère encore une autre erreur

    not well-formed at line 1169, column 7, byte 22626 at /opt/perl/lib/site_perl/5.6.1/PA-RISC1.1-thread-multi/XML/Parser.pm line 168

    Donc peu être que l'environnement perl que j'utilise n'est pas complètement à jours. Je testerais le script sur une environnement windows pour voir ce que ça donne sur mon fichier volumineux.

  19. #19
    Responsable Perl et Outils

    Avatar de djibril
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    19 820
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 19 820
    Points : 498 771
    Points
    498 771
    Par défaut
    ça n'a absolument rien à voir avec perl.
    not well-formed at line 1169, column 7, byte 22626 at /opt/perl/lib/site_perl/5.6.1/PA-RISC1.1-thread-multi/XML/Parser.pm line 168
    signifie que le fichier xml est mal formé tout simplement.

Discussions similaires

  1. Réponses: 2
    Dernier message: 01/02/2012, 15h02
  2. Méthode pour lire un fichier texte
    Par toutounesan dans le forum C++
    Réponses: 2
    Dernier message: 25/09/2007, 17h31
  3. Réponses: 6
    Dernier message: 08/04/2005, 03h00
  4. [TP]comment faire pour lire un fichier son
    Par sovo dans le forum Turbo Pascal
    Réponses: 1
    Dernier message: 19/09/2004, 19h33
  5. Probleme pour lire un fichier Ini
    Par Sebinou dans le forum C++Builder
    Réponses: 11
    Dernier message: 10/03/2004, 23h22

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