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 :

Comparer deux fichiers bit à bit


Sujet :

C++

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    43
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 43
    Points : 25
    Points
    25
    Par défaut Comparer deux fichiers bit à bit
    Comment comparer 2 fichiers bit à bit ?

    Bonjour à tous et encore merci pour votre aide et patience pour les « non professionnel » en programmation.
    Pourquoi ce programme, l’anecdote vaut le coup : Je bosse normalement dans le son. J’ai quelques personnes autour de moi dissent que le son change si l’on fait des copies.
    Ce petit programme va donc servir simplement à comparer deux exemplaires d’un même fichier copié x fois et nous dire s’il y des différences.
    On en déduira que non et donc que la différence de son est due : au débit du matériel de stockage, à l’interface de ce matériel de stockage, au logiciel en fonction de la piste utilisé ( algo interne )… à voir.

    Peut être avec vous une autre méthode… je suis toujours preneur.

    Voici la mienne :
    J’utilise deux Flux : A et B et je les compare.

    1er test avec le .tellg() sur le fluxB en commentaire.
    Pour commencer je ne comprends pas pourquoi ligne 44 :
    Si je fait un .tellg () sur un seul des flux ils commence à se décaler. Comme si la lecture de la position faisait avancer le pointeur de flux d’un octet. Normal ou étrange ?

    2eme test en activant les deux .tellg()
    Là la comparaison entre deux fichiers identique se passe bien mais je ne comprends le pas entre deux positions. Vu que j’ai mis une variable « bufferSize » pour remplir un tableau de 10char = 10 octets avec le flux. Et meme si je me trompe dans le nombre d’octet (char = 1/2octet ou 2*octets) le pas devrait être régulier.
    Sur un petit fichier 213 Oct le pas diminue : 45 – 41 – 36 – 26 – 22 – 17 – 16 - 10
    Et le pas change aussi en fonction de la taille des fichiers : sur un fichier de 170ko j’obtiens des pas de 10 à 494.
    Mystère !

    Du coup j’ai vraiment l’impression de ne pas bien comparer les ficher et des sauter des informations. Merci d’avance.

    Le code fonctionne. Pour l’utiliser mettre au niveau de l’exécutable deux fichiers renommé : testA.txt et testB.txt
    c’est juste que l’application une fois finie aura une petite interface graphique créé avec la lib Qt.

    main.cpp
    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
     
    #include <QApplication>
    #include <string>
    #include <iostream>
    #include <fstream>
    #include "CompareFiles.h"
     
    int main(int argc, char* argv[])
    {
        QApplication app(argc, argv);
     
        CompareFiles test;
     
        return app.exec();
    }
    CompareFiles.h
    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
    #ifndef COMPAREFILES_H
    #define COMPAREFILES_H
     
     
    class CompareFiles
    {
      public:
        CompareFiles(std::string a ="testA.txt", std::string b="testB.txt", int buff = 10, int delta = 4);
        virtual ~CompareFiles();
      protected:
      private:
        void compare();
        double tailleFichier( std::ifstream *flux );
        void affichageDiff(int i);
        void affichageDiff(char* bufA, char* bufB, int i);
     
        std::ifstream fluxA;
        std::ifstream fluxB;
        double tailleA, tailleB;
        int bufferSize;
        int deltaDiff;
    };
     
    #endif // COMPARFILES_H
    CompareFiles.cpp
    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
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    #include <string>
    #include <iostream>
    #include <fstream>
    #include <bitset>
    #include "CompareFiles.h"
     
     
    using namespace std;
     
    CompareFiles::CompareFiles(string a , string b , int buff, int delta )
                            : bufferSize(buff), deltaDiff(delta)
    {
      fluxA.open( a.c_str(), ios::in );
      if ( fluxA ) tailleA = tailleFichier ( &fluxA );
      else cerr << "Probleme dans le constructeur du flux A" << endl;
     
      fluxB.open( b.c_str(), ios::in );
      if ( fluxB ) tailleB = tailleFichier ( &fluxB );
      else cerr << "Probleme dans le constructeur du flux B" << endl;
     
      compare();
      cerr << "Fin";
    }
     
    void CompareFiles::compare(){
      int positionA, positionB;
      char*bufferA;
      char*bufferB;
     
      if ( tailleA == tailleB ) {
        // allocate memory:
        bufferA = new char [bufferSize];
        bufferB = new char [bufferSize];
     
        double counter = 0;
        while ( fluxA.good() && fluxB.good() && fluxA.tellg()< tailleA ) {
     
          // read data as a block:
          fluxA.readsome (bufferA,bufferSize);
          fluxB.readsome (bufferB,bufferSize);
     
          cerr << "position du flux : " << fluxA.tellg() << endl;
          // !!!!!!!!!!!!!!!!!!!!!!!!!!
          cerr << "position du flux : " << fluxB.tellg() << endl; // ici faut m'expliquer
          // !!!!!!!!!!!!!!!!!!!!!!!!!!
     
          for ( int i=0; i<bufferSize; i++ ) {
            if ( bufferA[i] != bufferB[i] ) {
              positionA = fluxA.tellg(); // On garde la position pour y revenir.
              positionB = fluxB.tellg(); // On garde la position pour y revenir. Normalement ils devraient avoir la meme position.
     
              cerr << "position du fluxA detect Err: " << positionA << endl;
              cerr << "position du fluxB detect Err: " << positionB << endl;
              cerr << "counter : " << counter << "  bufferSize : " << bufferSize << "  i : " << i << endl;
              cerr << "difference entre A et B à l'octet : " << counter*bufferSize + i << endl;
     
              affichageDiff(bufferA, bufferB, i);
              fluxA.seekg(positionA);
              fluxB.seekg(positionB);
            }
          }
          counter++;
        }
     
        delete[] bufferA;
        delete[] bufferB;
     
      }
      else cerr << "la taille des fichiers est differente" << endl;
    }
     
    double CompareFiles::tailleFichier( ifstream *flux ) {
      // determine la taille d'un fichier
      double length;
      flux->seekg (0, ios::end);
      length = flux->tellg();
      flux->seekg (0, ios::beg);
      cout << "taille " << length << endl;
      return length;
    }
    void CompareFiles::affichageDiff(int i){
     
      cerr << "position err : " << i << endl;
     
      if (i>deltaDiff) i-=deltaDiff;
      else i=0;
     
      cerr << "position du flux pour err : " << i << endl;
     
      fluxA.seekg(i);
      fluxB.seekg(i);
     
      for ( int k = 0; k<2; k++){
        if (k==0){
          cerr << "A : ";
          //fluxA.seekg(i);
        }
        else {
          cerr << "B : ";
          //fluxB.seekg(i);
        }
        for (int j = 0; j < 2*deltaDiff+5; j++) {
          if (k==0) cerr << "p" << fluxA.tellg() << "." << fluxA.get() << " ";
          else cerr << "p" << fluxB.tellg() << "." << fluxB.get() << " ";
        }
        cerr << endl;
      }
    }
    void CompareFiles::affichageDiff(char *bufA, char *bufB, int i){
      // cerr << b2;
      cerr << "Element A " << std::bitset<8>(bufA[i-1]) << " " << std::bitset<8>(bufA[i]) << " " << std::bitset<8>(bufA[i+1]) <<endl;
      cerr << "Element B " << std::bitset<8>(bufB[i-1]) << " " << std::bitset<8>(bufB[i]) << " " << std::bitset<8>(bufB[i+1]) << endl;
    }
     
     
     
     
    CompareFiles::~CompareFiles()
    {
      fluxA.close();
      fluxB.close();
    }

  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 : 61
    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
    Points : 50 367
    Points
    50 367
    Par défaut
    Je n'ai pas bien regardé dans le code mais peut qu'il faut ouvrir les fichiers en binaire ? Je ne suis pas sûr que l'ouverture par défaut d'un fichier soit en binaire mais plutôt en mode texte (avec interprétation et saut de certains caractères).
    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
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    43
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 43
    Points : 25
    Points
    25
    Par défaut
    Ok Merci je teste tout de suite. c'est vrai! suis je bête....

  4. #4
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    43
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 43
    Points : 25
    Points
    25
    Par défaut
    Super merci le Point 2 est résolu!
    en revanche j'ai toujours le même phénomène sur le point 1 je pense que c'est propre au fonctionnement de la fonction mais si quelqu'un peut me le confirmer.
    Merci ram-0000 pour cet œil de lynx.

  5. #5
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    43
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 43
    Points : 25
    Points
    25
    Par défaut
    Suite à quelques teste :
    si on modifie la valeur par défaut du bufferSize dans compareFiles.h
    je n'ai plus de problème dés que la valeur est supérieure a 511. Pourquoi?
    Là je crois qu'il faut un fou furieux des Jeans. Mais en info... je ne connais pas ce nombre magique.

  6. #6
    Rédacteur

    Avatar de Davidbrcz
    Homme Profil pro
    Ing Supaéro - Doctorant ONERA
    Inscrit en
    Juin 2006
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ing Supaéro - Doctorant ONERA

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Points : 4 732
    Points
    4 732
    Par défaut
    Pourquoi ne pas juste calculer les hash MD5 des differents fichiers et comparer ? Car ouvrir, lir et comparer les fichiers, cest un poil overkill
    "Never use brute force in fighting an exponential." (Andrei Alexandrescu)

    Mes articles dont Conseils divers sur le C++
    Une très bonne doc sur le C++ (en) Why linux is better (fr)

  7. #7
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    43
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 43
    Points : 25
    Points
    25
    Par défaut
    Ben tout simplement parce que je ne connaissais pas .
    J'ai un peu regardé c'est vrai que c'est une bonne idée... je vais le faire en parallèle.
    Je garde aussi la méthode de brutos car on ne compte pas vraiment faire des milliards de comparaisons mais juste quelques testes et je pense que de " voir le processus " les rassurera.

    Je n'ai toujours pas compris ce qui se passe dans la question 1.
    A bientôt.

  8. #8
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    43
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 43
    Points : 25
    Points
    25
    Par défaut
    En fait je dois le faire bit à bit car les fichiers peuvent être diffèrent et ce n'est que les datas que je compare.
    Maintenant j'ai un autre soucis :

    le flux est ouvert en binary. Mais rien ne se passe, la variable ne change meme pas de valeur et je n'ai aucune erreur???

    voici les methodes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    short int RechercheInFile::valShortIntAt(long int p){
      short int n = 0;
      flux.seekg(p);
      flux >> n;
      return n;
    }
    int RechercheInFile::valIntAt (long int p){
      int n = 0;
      flux.seekg(p);
      flux >> n;
      return n;
    }

  9. #9
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    43
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 43
    Points : 25
    Points
    25
    Par défaut
    ces méthodes me servent à lire le "head" d'un fichier wav.
    Donc par exemple je sais qu'a l'octet 30 je dois récupérer 2 octets pour connaitre le nombre de canaux ou 4 pour avoir la taille etc.

    Après quelques testes, je découvre que flux.tellg(), après l'opérateur >> est de -1. soit une erreur de lecture je crois.

    j'ai donc télécharger un éditeur hexa pour voir la gueule du fichier et j'ai bien des infos à lire à cet emplacement.

    n'aurai-je pas la bonne méthode?

    Quel est le problème dans mes méthodes?

    Encore merci d'avance. car j'ai lu la doc ifstream de long en large je ne comprends toujours pas.

  10. #10
    Membre émérite

    Inscrit en
    Mai 2008
    Messages
    1 014
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 1 014
    Points : 2 252
    Points
    2 252
    Par défaut
    Bonjour,

    Si tu veux lire du pur binaire, il faut :

    1) Ouvrir le flux avec std::ios::binary
    2) Mais surtout, n'utiliser que les fonctions membres read() et write().

    Toute autre utilisation, en particulier celle des opérateurs << et >> entraine une lecture en mode texte.

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

    Informations professionnelles :
    Activité : aucun

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

    Si les deux fichiers ne sont pas trop volumineux, tu peux toujours envisager de les charger entièrement dans deux vecteurs distincts, puis comparer ceux-ci.

    La FAQ pourrait t'aider à le faire, mais, en gros, cela pourrait prendre un style proche de:
    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
    std::string const compareFiles(std::string const & f1, std::string const & f2)
    {
        //ouverture des fichiers
        std::ifstream ifs1(f1.c_str(),std::ios_base::binary);
        std::ifstream ifs2(f2.c_str(),std::ios_base::binary);
        /* comparaison de leur taille (on considère qu'ils sont différents d'office
         * s'ils n'ont pas la même taille
         */
        // sauvegarder la position courante
        long pos1 = ifs1.tellg();
        long pos2 = ifs2.tellg();
        // se placer en fin de fichier
        ifs1.seekg( 0 , std::ios_base::end );
        ifs2.seekg( 0 , std::ios_base::end );
        // récupérer la nouvelle position = la taille du fichier
        long size1 = ifs1.tellg() ;
        long size2 = ifs2.tellg() ;
        // restaurer la position initiale du fichier
        ifs1.seekg( pos,  std::ios_base::beg ) ;
        ifs2.seekg( pos,  std::ios_base::beg ) ;
        if(size1!=size2)
            return "Files size are different";
        /* si on arrive ici, les fichiers sont déjà de même taille,
         * on peut donc les charger pour en comparer le contenu
         */
        std::vector<unsigned char> tab1(size1);
        std::vector<unsigned char> tab2(size1);
        ifs1.read(&tab1,size1);
        ifs2.read(&tab2,size1);
        bool areSame = true;
        for(size_t i=0;i<size1;++i)
        {
            if(tab1[i]!=tab2[i])
            {
                std::cout<<"file are different at offset"<< sd::hex<<i<<std::endl;
                areSame=false;
            }
        }
        if(areSame)
            return "files are same";
        return "files are differents";
    }
    cela pourrait s'utiliser sous une forme proche de
    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
    int main()
    {
        /* permettons nous de faire plusieurs comparaisons à la suite */
        bool again = true;
        while(again)
        {
            std::string f1;
            std::string f2;
            std::cout<<"give me first file's name ";
           std::cin>>f1;
           std::cout<<"give me second file's name ";
           std::cin>>f2;
           std::cout<<compareFiles(f1,f2)<<std::endl;
           std:::cout<<"do you want compare other files (Y / N) ?";
           std::string in;
           std::cin>>in;
           if(in=="no" || in=="NO" or in=="N" or in=="n")
               again=false;
        }
        std::cout<<"See you soon"
        cin.ignore( numeric_limits<streamsize>::max(), '\n' );
        return 0;
    }
    C'est du vite fait, et donc surement améliorable
    [EDIT]Pour info : le calcul de la somme MD5 (ou de tout autre somme de controle) nécessite aussi la lecture du fichier, et nécessite, en plus, le passage à la "moulinette" de l'algorithme
    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

  12. #12
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    43
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 43
    Points : 25
    Points
    25
    Par défaut
    Désolé de ne pas avoir répondu plus tôt. J'étais à un mariage vraiment super émouvant sur les bord du lac Lemant. Enfin je ne vais pas vous raconter ma vie... lol.

    Merci à tous pour votre aide. J'ai enfin fini mon petit programme. tout fonctionne. il n'y à pas vraiment de garde fou pour éviter les manipulations farfelue mais il marche!!!
    Je ne sais pas si vous désirez les sources du coup. pour voir comment je m'en suis dépatouillé, ou même le tester. n'hésitez pas à demander et par la même occasion me dire où le poster. Je suis toujours preneur de conseille et de méthode de développement.

    A+.

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

Discussions similaires

  1. comparer deux fichier .xls
    Par oursquetaire dans le forum Excel
    Réponses: 6
    Dernier message: 06/07/2006, 16h52
  2. [JDOM] Comparer deux fichiers XML en Java
    Par calimero2611 dans le forum Format d'échange (XML, JSON...)
    Réponses: 5
    Dernier message: 30/06/2006, 11h19
  3. Comparer deux fichier
    Par Taz_8626 dans le forum Langage
    Réponses: 3
    Dernier message: 20/06/2006, 11h46
  4. comparer deux fichiers avec une api windows
    Par sweetdreamer dans le forum Windows
    Réponses: 4
    Dernier message: 25/05/2006, 22h10
  5. Fonction c qui compare deux fichiers ???
    Par babyface dans le forum C
    Réponses: 4
    Dernier message: 19/11/2005, 13h07

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