Crc 32bits compatible winzip

Soyez le premier à donner votre avis sur cette source.

Snippet vu 7 064 fois - Téléchargée 30 fois

Contenu du snippet

Salut,

J'ai cherché en vain des explications sur la méthode de calcul d'un CRC 32 bits sur le net. On ne tombe que sur des sites qui vous bourrines de formules mathématiques que si tu sorts pas tout juste de BTS beh tu peut toujours courir pour comprendre. (moi j'ai quitté l'école depuis trop longtemps pour me souvenir de formules comme celles là).
Bref je suis tombé sur ce site en anglais => http://www.createwindow.com/programming/crc32/ qui n'explique toujours pas comment obtenir ce résulat de manière simple mais qui donne en tout les cas le source d'un calcul CRC32 sur une chaîne de caractères.
J'ai repris ce code, j'ai dégagé tout ce qui était MFC et programmation orientée Objet (oui je vous l'ai dit, ça fait longtemps que j'ai quitté le bahut et de mon temps y avait que du C et pas de C++) pis je l'ai adapté pour qu'il calcule le CRC32 d'un fichier quelconque (Attention ce fichier ne doit pas excéder 4Go mais bon j'en connais peu des fichiers comme ça ;).
Alors bon, ça fonctionne très bien. Vous pouvez le confirmer en affichant la colonne CRC dans Winzip (bouton droit dans les colonnes de Winzip et cocher CRC).
Je suis dégouté, j'aurais voulu le pondre moi-même ce code mais faute d'informations sur le CRC32 y'a fallu trouver une autre astuces.....la re-pompe...

Pour utiliser la fonction, il suffit par exemple de faire une ligne (ou 2 ;) comme celà:

DWORD TailleFichier;
DWORD CRC32 = CRC32_Fichier ("c:\\MonFichier.exe",&TailleFichier);

Ah oui, j'en profite pour récupérer la taille du fichier. C'est utile pour mon projet mais rien ne vous empêche de le faire sauter.

Bonne redondance et @+.

Source / Exemple :


// *****************************************************************
// Permet de créer la table de référence CRC32 compatible Winzip en swappant 
// les bits. Swap bit 0 avec bit 7, bit 1 avec bit 6, bit 2 avec bit 5 etc etc...
// *****************************************************************
DWORD Reflect(DWORD ref,char ch) 
	{
    DWORD value(0); 
	
	for(int i=1;i<(ch+1);i++) 
	{ 
		if (ref & 1) value|=1 << (ch-i); 
		ref>>=1; 
	} 
	return value; 
	}

// ******************************************************************
// Renvoi la Valeur CRC32 d'un Fichier (0 en cas d'erreur)
// J'en profite pour renvoyer la taille du fichier (1 pierre 2 coups)
// c'est utile pour le projet que je développe actuellemnt...désolé ;)
// PS: vu sur http://www.createwindow.com/programming/crc32/
// ******************************************************************
DWORD CRC32_Fichier(char *NomFichier,DWORD *TailleFichier)
{
	DWORD CRC32=0;				// Valeur de retour de la fonction 
	DWORD crc32_table[256];		   // Table identique a celle utilisée dans 
	DWORD ulPolynomial=0x04c11db7; // Winzip etc...
	HANDLE Hfich;				// Handle du fichier
	DWORD cmpt;					// Compteur d'octets pour lecture fichier
	unsigned char *octet,*poct;	// octets lus
	DWORD nb_lus;				// Nombre d'octets lus 

	// Début

  • TailleFichier=0; // Bon OK ça sert à rien ;) c plus propre c tout
// Ouverture Fichier. Si Echec alors Fonction Renvoi 0 et sort immediatement if ((Hfich=CreateFile(NomFichier,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_FLAG_SEQUENTIAL_SCAN,NULL))==INVALID_HANDLE_VALUE) return CRC32; // Récupére Taille du Fichier. Si Echec alors Fonction Renvoi 0 et sort immediatement if ((*TailleFichier=GetFileSize(Hfich,0))==0xFFFFFFFF) return CRC32; // Génération table de référence CRC32 for(int i=0;i<=0xFF;i++) { crc32_table[i]=Reflect(i,8)<<24; for (int j=0;j<8;j++) crc32_table[i]=(crc32_table[i]<<1)^(crc32_table[i]&(1<<31)?ulPolynomial:0); crc32_table[i]=Reflect(crc32_table[i],32); } // Allocation Memoire si pas possible Retour avec CRC32=0 cmpt=*TailleFichier; if ((octet=(unsigned char *)malloc(cmpt+1))==NULL) { CloseHandle(Hfich); // Fermeture du Fichier return 0; // Retourne 0 => Erreur } // Lecture Complête du Fichier en mémoire allouée précedement if (ReadFile(Hfich,octet,cmpt,&nb_lus,NULL)==0 || nb_lus!=cmpt) // Erreur M.... ! { free(octet); // Libération mémoire CloseHandle(Hfich); // Fermeture du Fichier return 0; // Retourne 0 => Erreur } // Calcul du CRC32 du Fichier CRC32=0xFFFFFFFF; // Départ avec tous les bits à 1 poct=octet; while (cmpt--) // Tant qu'on a pas atteind la fin de fichier CRC32=(CRC32>>8)^crc32_table[(CRC32 & 0xFF)^*poct++]; // Fermeture du Fichier CloseHandle(Hfich); free(octet); // Libération mémoire return CRC32^0xFFFFFFFF; }

Conclusion :


Je le rappele, ce code est une adaptation de celui que j'ai trouvé a cette adresse:
http://www.createwindow.com/programming/crc32/

Pour ceux qui ne savent pas, le CRC 32bits permet avec une simple valeur 32 bits de réaliser comme une empreinte digitale d'un fichier. Si un seul octet change dans le fichier, alors le CRC sera modifié également.
Ca permet de s'affranchir d'eventuels erreurs d'écriture disque ou transfert par FTP ou port série voir d'infection par Virus ou modification de code etc etc....tout est imaginable.

MODIFICATION:
OK j'ai modifié le source pour utiliser de la mémoire dynamique afin de lire le fichier d'une traite et non plus octet par octet. Le gain de temps est bien sûr on s'en serais douté énorme.
Par contre, il faut oublier les fichiers gigantesques. J'ai tenté un fichier 2,6 Go et bien sûr je me suis vu refusé la réservation mémoire. (nan je n'y ait pas cru mais j'ai tenté)
J'ai revu mes prétentions a la baisse et j'ai fait le test sur un fichier de 650 Mo. La réservation mémoire à été accepté mais alors le temps de traitement à été énorme (~7min). Forcément, le fichier d'échange windows à été mis à rude épreuve avec l'antivirus actif etc... Enfin le résultat de CRC s'est avéré bon et c'est là l'essentiel.
Pour de petits fichiers de 50Mo etc... la vitesse de traitement est de moins d'une seconde sur mon P4 2,8GHz 512Mo RAM...c'est appréciable (pour en dire plus, 12 secondes pour un fichier de 361 Mo) La différence est lorsque la RAM n'est plus suffisante. Windows se met à utiliser un fichier d'échange et là les temps deviennent indécents.
Donc je n'y touche plus surtout que moi mon but est de traiter de petits fichiers de moins de 5Mo.

A voir également

Ajouter un commentaire

Commentaires

Messages postés
64
Date d'inscription
mercredi 24 juillet 2002
Statut
Membre
Dernière intervention
26 novembre 2009

Intéressant... C'est vrai que c'est pas très digeste les formules polynomiales dans le corps F2... oups je m'écarte du sujet...
Ouais ca risque d'être sympa à porter en C#, cependant tu peut faire le malin et te faire juste une petite DLL C++.NET dans laquel tu encapsule ce code, avec les convertions nécessaires et pouf fini.
Mais bon, c'est plus drôle de convertir ^^
Messages postés
57
Date d'inscription
lundi 23 février 2004
Statut
Membre
Dernière intervention
11 septembre 2008
1
Nikel v( ^_^ )v

Ca fait quelque temps que je cherche à calculer un CRC32 en C# , mais c'est pas evident d'avoir des infos (compréensibles pour moi tout du moins) .
J'ai bien galéré à faire afficher un DWORD (^^ ben ui) à l'écran mais ça marche parfaitement !
Vive le c++ lol
'me reste plus qu'a le porter en C# !

Etonnant le generateur pour la table , je pensais pas que c'etait possible .

bravo , Well done !!!
Messages postés
21042
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
21
Cette source est a base de pur code API Windows alors gtk....
Tente plutot de reposer ta question sur une source 'banquise'.
Messages postés
13
Date d'inscription
vendredi 2 juillet 2004
Statut
Membre
Dernière intervention
3 août 2004

help
depuis une semaine j essaie de faire du graphique avec gtk et j arrive pas à utiliser les biblio
je dois mal matriser le logiciel dev-C++4.0
j ai meme installé le 5.0 parce que j ai trouvé un site ou il tout est expliqué normalement mais ca marche pas non plus
et avec windows.h j ai pas trouvé de site qui explique un peu les fonctions en C!
donc voila je commence a etre dans la merde donc si quelqu un pouvait m aider un peu ca serait vraiment sympa
merci
Messages postés
21042
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
21
y avait pas besoin d'allouer (HeapAlloc ou VirtualAlloc en win32) le tout, un buffer 1 Mo suffisait et tu bouclais dessus tant que ReadFile donnait des octets, ça aurait permis de traiter fichiers de toutes tailles.
Voila l'idee pour ta prochaine source.
Bonne continuation.

LordBob > faut 2 minutes pour un faire un WinMain appelant ces fonctions.
Afficher les 8 commentaires

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.