Bonjour !
J'aurais besoin d'une fonction qui permette de savoir si deux fichiers quelconques sont identiques (même avec des noms différents).
Comment feriez-vous ça ?
Bonjour !
J'aurais besoin d'une fonction qui permette de savoir si deux fichiers quelconques sont identiques (même avec des noms différents).
Comment feriez-vous ça ?
Mon site personnel consacré à MSEide+MSEgui : msegui.net
Bonjour,
Plusieurs moyens :
- le plus simpliste
- Comparer les tailles
- Si tailles égales
- comparer byte à byte
- plus élaboré
- Comparer les tailles
- Si tailles égales
- calculer les hash (CRC ou md5 .... au choix)
Si les cons volaient, il ferait nuit à midi.
Merci droggo pour la réponse.
Donc à la limite on pourrait faire comme ça ?
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 type Octet = Byte; TFichier = file of Octet; function CompareFichiers(const aNomFichier1, aNomFichier2: string): Boolean; var fichier1, fichier2: TFichier; octet1, octet2: Octet; begin {$I-} AssignFile(fichier1, aNomFichier1); result := IOResult = 0; if not result then Exit; AssignFile(fichier2, aNomFichier2); result := IOResult = 0; if not result then Exit; {$I+} try Reset(fichier1); Reset(fichier2); while result and (not EOF(fichier1)) and (not EOF(fichier2)) do begin Read(fichier1, octet1); Read(fichier2, octet2); result := octet1 = octet2; end; if result then result := EOF(fichier1) and EOF(fichier2); finally CloseFile(fichier1); CloseFile(fichier2); end; end; begin WriteLn(CompareFichiers('image.jpg', 'image - Copie.jpg')); end.
Mon site personnel consacré à MSEide+MSEgui : msegui.net
Bonjour,
Je ne suis pas allé plus loin que ça, car si c'est ok pour fichier1 et que ça échoue pour fichier2, tu ne libères pas fichier1.
D'accord, c'est une variable locale, mais c'est un principe de base de tout nettoyer, et de ne pas compter sur le système pour le faire.
Et un peu plus loin, il faudrait aussi vérifier les reset
ET contrôler les tailles des fichiers AVANT de commencer la comparaison octet à octet, qui est inutile si les tailles sont différentes.
Si les cons volaient, il ferait nuit à midi.
Merci droggo.
J'ai revu ma copie en essayant de prendre en compte tes remarques.
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 type Octet = Byte; TFichier = file of Octet; function CompareFichiers(const aNomFichier1, aNomFichier2: string): Boolean; var fichier1, fichier2: TFichier; octet1, octet2: Octet; tailleFichier1, tailleFichier2: Int64; begin AssignFile(fichier1, aNomFichier1); AssignFile(fichier2, aNomFichier2); {$I-} Reset(fichier1); result := IOResult = 0; if result then begin Reset(fichier2); result := IOResult = 0; if not result then CloseFile(fichier1); end; {$I+} if not result then Exit; tailleFichier1 := FileSize(fichier1); tailleFichier2 := FileSize(fichier2); result := tailleFichier1 = tailleFichier2; if not result then begin CloseFile(fichier1); CloseFile(fichier2); Exit; end; while result and not EOF(fichier1) do begin Read(fichier1, octet1); Read(fichier2, octet2); result := octet1 = octet2; end; CloseFile(fichier1); CloseFile(fichier2); end; begin WriteLn(CompareFichiers('image.jpg', 'image - Copie.jpg')); end.
Mon site personnel consacré à MSEide+MSEgui : msegui.net
Une variante (beaucoup plus rapide) utilisant BlockRead au lieu de Read :
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 type Octet = Byte; TFichier = file of Octet; function CompareFichiers(const aNomFichier1, aNomFichier2: string): Boolean; const TAILLE_TAMPON = 256; var fichier1, fichier2: TFichier; tailleFichier1, tailleFichier2: Int64; tampon1, tampon2: array[0..TAILLE_TAMPON - 1] of Octet; octetsLus, iOctet: Word; begin AssignFile(fichier1, aNomFichier1); AssignFile(fichier2, aNomFichier2); {$I-} Reset(fichier1, 1); result := IOResult = 0; if result then begin Reset(fichier2, 1); result := IOResult = 0; if not result then CloseFile(fichier1); end; {$I+} if not result then Exit; tailleFichier1 := FileSize(fichier1); tailleFichier2 := FileSize(fichier2); result := tailleFichier1 = tailleFichier2; if not result then begin CloseFile(fichier1); CloseFile(fichier2); Exit; end; repeat BlockRead(fichier1, tampon1, TAILLE_TAMPON, octetsLus); BlockRead(fichier2, tampon2, TAILLE_TAMPON, octetsLus); iOctet := 0; while result and (iOctet < octetsLus) do begin result := tampon1[iOctet] = tampon2[iOctet]; Inc(iOctet); end; until octetsLus < TAILLE_TAMPON; CloseFile(fichier1); CloseFile(fichier2); end; begin WriteLn(CompareFichiers('image.jpg', 'image - Copie.jpg')); end.
Mon site personnel consacré à MSEide+MSEgui : msegui.net
Bonjour,
Oui, BlockRead a toujours été la bonne méthode pour ce genre de travail, je m'en étais entre autres servi pour mon implémentation de calculs de hash (CRC, md*, ...)
ps : ne me demande pas mon code pour ces fonctions, c'est mon employeur de l'époque qui en est propriétaire.
Si les cons volaient, il ferait nuit à midi.
salut
utiise les TMemorystream c'est pratique
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 function CompareFiles(aBaseFileName,aCompareFileName : String): boolean; begin Result := FALSE; //Instantiate the two memory streams FBaseStream := TMemoryStream.Create; FCompareStream := TMemoryStream.Create; try //Load both files into their respective streams... FBaseStream.LoadFromFile(aBaseFileName); FCompareStream.LoadFromFile(aCompareFileName); //...and compare them Result := (FBaseStream.Size = FCompareStream.Size) and CompareMem(FBaseStream.Memory, FCompareStream.Memory, FBaseStream.Size); finally //Tidy up FBaseStream.Free; FCompareStream.Free; FBaseStream := Nil; FCompareStream := Nil; end; end;
Blaise PascalNous souhaitons la vérité et nous trouvons qu'incertitude. [...]
Nous sommes incapables de ne pas souhaiter la vérité et le bonheur, et sommes incapables ni de certitude ni de bonheur.
PS : n'oubliez pas le tag
Merci pour vos réponses. Je crois que nous avons plus ou moins fait le tour du sujet.
Il y a cependant encore une chose sur laquelle j'aimerais vous questionner, ce sont les "calculs de hash" dont parlait droggo. En un mot, qu'est-ce que c'est ? Et en quoi cela peut-il se substituer (avantageusement ou non) à une comparaison octet par octet ?
Mon site personnel consacré à MSEide+MSEgui : msegui.net
Hello
Pour des questions de performance, j'essaierai de lire des blocs de taille fixe (par exemple, 16k ou 32k, mais ça dépend de la taille du fichier et donc du nombre de blocs à traiter par la suite) puis de calculer un checksum sur ces blocs puis de les comparer.
Les checksum/hash permettent d'avoir une sorte de signature d'un volume de données. Si les signatures sont égales, les blocs de données sont égaux. Tu peux regarder md5 pour cela, il devrait exister des implémentations Pascal...
M.Dlb - Modérateur z/OS - Rédacteur et Modérateur Pascal
Merci pour ta réponse. Ah oui, tiens, il existe une unité md5 livrée avec FPC.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14 uses md5; var hash1, hash2: string; begin hash1 := MD5Print(MD5File('image1.jpg')); hash2 := MD5Print(MD5File('image2.jpg')); WriteLn(hash1); WriteLn(hash2); WriteLn(hash1 = hash2); ReadLn; end.
Mon site personnel consacré à MSEide+MSEgui : msegui.net
Bonjour,
N'y aurait-il pas une erreur fondamentale dans ce prédicat ?
Il me semble qu'au contraire c'est la différence des signatures qui indique, à coup sûr, que les données sont différentes.
L'égalité des signatures ne constituant qu'une probabilité d'égalité des données.
Par ailleurs, en termes de performances, l'emploi de clés (CRC, MD5, etc.) pour comparer deux fichiers ne seraient intéressante que si les clés étaient pré-calculées et embarquées dans les fichiers de donnée. Sinon le calcul des clés nécessitera le parcours intégral des deux fichiers ce qui prendra toujours plus de temps que la comparaison simple laquelle peut cesser dès la première différence trouvée.
Si les cons volaient, il ferait nuit à midi.
Merci pour vos réponses.
J'ai rassemblé dans une unité les solutions proposées (plus une autre que j'ai trouvée ailleurs) et écrit un programme de test. Les temps d'exécution varient tellement d'une fois à l'autre qu'il est impossible d'en tirer une conclusion. Tout ce que j'ai remarqué, c'est que la taille des blocs lus influe beaucoup sur le temps d'exécution.
J'ai retouché la fonction que j'avais postée plus haut, parce que je me suis aperçu que je n'avais pas suffisamment pris en compte le cas de deux fichiers différents mais de taille identique.
Mon site personnel consacré à MSEide+MSEgui : msegui.net
Bonsoir,
petite modif en bas du fichier test.pas, afin de lui faire accepter deux paramètres sur la ligne de commande, ce qui est bien sympathique à l'usage
mise en commentaire des deux lignes de constantes, et ajout de 3 lignes :
Pas touché au reste, et ma foi, ça fonctionne.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12 {const FICHIER1 = 'fichier1.zip'; // **** à modifier **** FICHIER2 = 'fichier2.zip'; // **** à modifier **** } var i: integer; FICHIER1,FICHIER2: string; // ajout begin FICHIER1 := paramstr(1); // ajout FICHIER2 := paramstr(2); // ajout
Bien joué, Roland !
Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peut–être qu'il peut être sûr, etc.
Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
Mes 2 cts,
--
jp
Bonjour à tous,
Une discussion intéressante. Je trouve que la remarque de DomDA91 est pertinente. En résumé, il y a un dilemme entre faire les choses de façon sûre mais lente et faire les choses efficacement avec des risques d'erreurs mais de façon plus rapide.
L'algorithme MD5 a une page wiki qui lui est dédiée : https://fr.wikipedia.org/wiki/MD5
Il n'est pas considéré comme sûr, d'autres algorithmes (qui ne seront jamais totalement sûrs puisqu'ils utilisent le hashage, deux objets de couleur rouge ne sont pas forcément identiques par exemple) ont été suggérés à sa place.
Du peu que je comprends, sans être expert.
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager