Crc 32bits compatible winzip

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

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.