[Perl] Comparaison de fichiers

Comparaison de fichiers [Perl] - Perl - Programmation

Marsh Posté le 11-07-2017 à 13:14:37    

Bonjour,
 
J'ai besoin de comparer basiquement 2 fichiers XML.
 
Le principe est si une ligne du xml2 n'est pas dans le xml1 alors j'écris la ligne dans un fichier de résultat.
 
j'ai écris le code suivant :

Code :
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. my $xml1="full.xml";
  5. my $xml2="full2.xml";
  6. my $result="result.txt";
  7. # Ouverture des fichiers
  8. open (fXML1, $xml1) or die "$xml1 : $!";
  9. open (fXML2, $xml2) or die "$xml2 : $!";
  10. # Copie du contenu des fichiers dans un tableau
  11. my @lines1=<fXML1>;
  12. my @lines2=<fXML2>;
  13. # Fermeture des fichiers
  14. close (fXML1);
  15. close (fXML2);
  16. # Afficher la taille des tableaux
  17. print scalar(@lines1)."\n";
  18. print scalar(@lines2)."\n";
  19. #création du fichier résultat
  20. open (fResult,">$result" ) or die "$result : $!";
  21. foreach my $line2 (@lines2)
  22. {
  23. my $present=0;
  24. foreach my $line1 (@lines1)
  25. {
  26.  if ($line1 eq $line2)
  27.  {
  28.   $present=1;
  29.   next;
  30.  }
  31. }
  32. if ($present==0)
  33. {
  34.  print fResult $line2;
  35. }
  36. }
  37. #fermeture du fichier résultat
  38. close (fResult);


 
Le problème c'est que mes XML font chacun plus de 300 000 lignes et c'est donc très long et gourmand en CPU.
Avez vous une piste pour optimiser ce genre de traitement  ?
 
Par avance merci.
 
:hello:

Reply

Marsh Posté le 11-07-2017 à 13:14:37   

Reply

Marsh Posté le 11-07-2017 à 14:03:42    

300.000 * 300.000 itérations ca fait beaucoup.
 
A mon avis il faut que tu arrives à trier tes lignes en amont.
Peu etre en fonction de la balise qui commence ta ligne.
 
Tu fais une map contenant le nom de la balise suivie des lignes ou elle se trouve. Au lieu d'itérer sur l'ensemble tu compares sur un plus petit sous ensemble.
 
Après si t'as beaucoup de balises avec des noms différents, c'est la merde.
 

Reply

Marsh Posté le 11-07-2017 à 14:15:01    

Merci The_Kid :jap:
 
En fouillant un peu plus sur le net je suis tombé sur Array:Utils.
 
j'ai donc adapté ça :
 

Code :
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. use Array::Utils qw(:all);
  5. my $xml1="full.xml";
  6. my $xml2="full2.xml";
  7. my $result="result2.xml";
  8. # Ouverture des fichiers
  9. open (fXML1, $xml1) or die "$xml1 : $!";
  10. open (fXML2, $xml2) or die "$xml2 : $!";
  11. # Copie du contenu des fichiers dans un tableau
  12. my @lines1=<fXML1>;
  13. my @lines2=<fXML2>;
  14. # Fermeture des fichiers
  15. close (fXML1);
  16. close (fXML2);
  17. # Afficher la taille des tableaux
  18. print scalar(@lines1)."\n";
  19. print scalar(@lines2)."\n";
  20. #création du fichier résultat
  21. open (fResult,">$result" ) or die "$result : $!";
  22. # check if arrays contain same members
  23. if ( !array_diff(@lines1, @lines2) )
  24. {
  25. print "Les xml sont identiques";
  26. }
  27. # get items from array @lines1 that are not in array @lines2
  28. my @minus = array_minus( @lines2, @lines1 );
  29. print fResult @minus;
  30. #fermeture du fichier résultat
  31. close (fResult);


 
Je suis en train de regarder mais à priori ça fait le taf.


Message édité par web_olivier le 11-07-2017 à 14:15:41
Reply

Marsh Posté le 12-07-2017 à 00:50:21    

Si c'est juste pour savoir quelles lignes de fichier2 ne sont pas dans fichier1 en se moquant de l'ordre des lignes,
 

Code :
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. use autodie;
  5.  
  6. my ($xml1, $xml2, $result) =('full1.xml', 'full2.xml', 'result.xml');
  7. my %xml1_lines;
  8.  
  9. open(my $fh, '<', $xml1);
  10. while (<$fh> ) {
  11.    $xml1_lines{$_}++;
  12. }
  13. close($fh);
  14.  
  15. open($fh, '<', $xml2);
  16. open(my $gh, '>', $result);
  17. while (<$fh> ) {
  18.    unless ($xml1_lines{$_}) {
  19.        print $gh $_;
  20.    }
  21. }
  22. close($gh);
  23. close($fh);


Bon, c'est codé à vue, donc SGDG, j'ai pu faire des typos.
 
Si tu veux vraiment exploiter la structure xml des fichiers, il faudrait plutôt utiliser XML::Diff
 
A+,


Message édité par gilou le 12-07-2017 à 11:13:04

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 24-07-2017 à 12:51:55    

Merci beaucoup Gilou :)

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed