Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1074 connectés 

  FORUM HardWare.fr
  Programmation
  Perl

  [Résolu][Perl] Découper un fichier en plusieurs et optimisation

 



 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

[Résolu][Perl] Découper un fichier en plusieurs et optimisation

n°2189589
Sethenssen
Posté le 10-05-2013 à 12:14:57  profilanswer
 

Bonjour,
 
J'ai un besoin simple,  
J'ai un fichier source toto.csv qui fait 18M et contient 1,1 millions de lignes.
Je souhaite le découper pour en faire autant de fichier de 100 000 lignes que nécessaire.
 
Pour cela j'ai réalisé un script qui fonctionne, mais le problème c'est qu'il met plusieurs heures !
Ce qui est complètement dingue.
 
Mon besoin initial était d'importer toto.csv en base MySQL dans une simple table sans aucun index, juste une clé primaire, mais cela met ~70mn (avec un load data infile qui plus est....je m'arrache aussi les cheveux pour comprendre pourquoi).
Alors je me suis dis que faire de même mais sur des fichiers plus petit me ferait gagner du temps et bien là c'est perdu.
 
Donc voici à quoi ressemble mon fichier source:

Code :
  1. 1002821311;TAPIS
  2. 1002166671;CHAISE
  3. 1002759082;CHAISE
  4. 1002558833;TABLE
  5. 1002318880;CHAISE
  6. 1002259114;TABLE
  7. 1002805492;CHAISE
  8. 1002074071;CHAISE
  9. 1002548136;CHAISE
  10. 1002884119;TAPIS


 
Voici mon code:

Code :
  1. #!/usr/bin/perl -w
  2. use warnings;
  3. use strict;
  4. # Global Variable
  5. my $DIR="/home/toto/tmp/";
  6. my $FILENAME = "toto.csv";
  7. my $OUT = $DIR . sprintf($FILENAME);
  8. my $maxline = 100000;
  9. my $size = $maxline;
  10. my $output = "file";
  11. my $num = 1;
  12. # Script
  13. open(TOP, "<", $OUT);
  14. while(<TOP> ) {
  15.         chomp;
  16.         if($. != $maxline) {
  17.                 open(FILE, ">>", $DIR.$output.$num);
  18.                 print FILE $., "\t", $_, "\n";
  19.                 close(FILE);
  20.         }
  21.         else {
  22.                 open(FILE, ">>", $DIR.$output.$num);
  23.                 print FILE $., "\t", $_, "\n";
  24.                 close(FILE);
  25.                 $maxline=$maxline+$size;
  26.                 $num++;
  27.         }
  28. }
  29. close(TOP);
  30. __END__


Message édité par Sethenssen le 10-05-2013 à 18:58:04
mood
Publicité
Posté le 10-05-2013 à 12:14:57  profilanswer
 

n°2189616
gilou
Modérateur
Modzilla
Posté le 10-05-2013 à 16:24:53  profilanswer
 

C'est très très simple, la lenteur, et ça sera pareil avec tout programme ainsi codé, que ce soit en Perl ou autre chose.  
Tu fais un open(File) et un close(File) (sans compter une opération de positionnement en fin de fichier) qui sont des opérations lentes une fois par ligne du fichier source, soit 2.2 Million d'opérations de ce type... [:bastian:3]  
A 1/100e de seconde par opération, on serait a plus de 6h
 
Un script de ce type devrait faire l'affaire:

Code :
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. use autodie;
  5.  
  6. # Global Variable
  7. my $DIR = '/home/toto/tmp/';
  8. my $FILENAME = 'toto.csv';
  9. my $maxline = 100000;
  10.  
  11. #
  12. my $outname = "file";
  13. my $fnum = 1;
  14. open(my $fout, ">", $DIR.$outname.sprintf("%03d", $fnum++));
  15.  
  16. # Script
  17. open(my $fin, "<", $DIR.$FILENAME);
  18. while (<$fin> ) {
  19.  print $fout $_;
  20.  if ($. % $maxline == 0) {
  21.    close($fout);
  22.    open($fout, ">", $DIR.$outname.sprintf("%03d", $fnum++));
  23.  }
  24. }
  25. close($fout);
  26. close($fin);
  27.  
  28. __END__


Le sprintf("%03d", $fnum++) c'est pour avoir des fichiers file001 file002 etc  
 
A+,


Message édité par gilou le 10-05-2013 à 18:46:54

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2189638
Sethenssen
Posté le 10-05-2013 à 18:57:35  profilanswer
 

Parfait, merci gilou ! Je passe de plusieurs heures à 2 sec...effectivement la mémoire en prenait un gros coup derrière la casquette.
 
You are the best.

n°2216292
frelinf
Posté le 16-01-2014 à 11:06:57  profilanswer
 

Bonjour,
 
Le programme fourni par Gilou (lors de la discussion  "Découper un fichier en plusieurs et optimisation" ) m'est particulièrement utile.
Cependant je cherche à le modifier quelque peu...
 
1) Je ne comprends pas les sens de "$. %" sur cette ligne :  

Code :
  1. if ($. % $maxline == 0)

.
 
2) J'essaie de modifier ce programme, pour que la découpe du fichier se fasse selon le contenu de la ligne (et non à la nième ligne).
Je souhaite découper le fichier quand la ligne commence par dièse, sachant que ce qui suit le dièse serait le nom à donner au fichier.
De type :
 

Code :
  1. # Global Variable
  2. my $FILENAME = 'test.txt';
  3.  
  4. open(my $fout, ">", $rep.$outname);
  5. $outname = "";
  6.  
  7. # Script
  8. open(my $fin, "<", $rep.$FILENAME);
  9. while (<$fin> ) {
  10.  
  11. if ($_ =~ /^#/) {
  12.   close($fout);
  13.   $outname = $_;
  14. $outname =~ s/#//;
  15.   #open($fout, ">", $rep.$outname.sprintf("%03d" . ".aa", $fnum++));
  16.   open($fout, ">", $rep.$outname);
  17. }
  18. else {
  19. print $fout $_;
  20. }
  21. }
  22. close($fout);
  23. close($fin);


 
ça ne fonctionne bien évidemment pas!
Je parviens à découper mon fichier si la ligne commence par "#", mais les nouveaux fichiers ne se nomme pas comme je le souhaite.
 
Quelqu'un peut-il me dire ce qui cloche.
 
D'avance merci,
 
Frelinf
 
La suite ici: http://forum.hardware.fr/hfr/Progr [...] 1182_1.htm


Message édité par gilou le 21-01-2014 à 15:11:47

Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  Perl

  [Résolu][Perl] Découper un fichier en plusieurs et optimisation

 

Sujets relatifs
[résolu] un fichier cpp, 2 compilateurs (g++ et avr-g++)FICHIER TEXTE en JAVA
Changer ligne d'un fichier textejonction fichier MYD vers Ramdisk -> useless ?
Insérer un ScrollBar dans un fichier xml - visite virtuelleFaire échap en expect
Aperçus de plusieurs sites dans une seule pagequelle volumétrie max du fichier de translation ".mo"
Aide pour la création d'un fichier bat pour ping sur réseauBatch Recherche fichier à partir d'une liste et Copier
Plus de sujets relatifs à : [Résolu][Perl] Découper un fichier en plusieurs et optimisation


Copyright © 1997-2018 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR