begin process at 2010 02 10 01:09:11
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Maths & Algorithmes

 > CRC32 COMPATIBLE WINRAR ET WINZIP ( BASÉ SUR LE CODE C++ DE CAPA6T )

CRC32 COMPATIBLE WINRAR ET WINZIP ( BASÉ SUR LE CODE C++ DE CAPA6T )


 Information sur la source

Note :
8 / 10 - par 1 personne
8,00 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10
Catégorie :Maths & Algorithmes Source .NET ( DotNet ) Classé sous :crc32 Niveau :Débutant Date de création :27/01/2005 Date de mise à jour :07/02/2005 21:03:47 Vu / téléchargé :14 216 / 404

Auteur : li9

Ecrire un message privé
Site perso
Commentaire sur cette source (16)
Ajouter un commentaire et/ou une note

 Description

Cliquez pour voir la capture en taille normale
Voici une classe qui vous permet de générer le CRC32 d'un fichier.
Je me suis basé sur la source C++ de Capa6T (http://www.cppfrance.com/code.aspx?ID=24351)
qui marche à merveille.
La conversion en C# n'a pas été très simple mais c'était un bon challenge.
J'ai aussi essayé de le rendre un peu plus rapide en lisant des block de 4ko au lieu de lire
byte par byte , ce qui peu rendre le calcul de fichiers volumineux tres long.
Je vous epargne les détails (si vous en voulez , les sources sont pleins de commentaires ^^ )

Vous pouvez vous servir directement de cette classe en l appelant ainsi :
uint crc = CRC32.GetCrc32( "nom_de_fichier.ext" , false , null ) ; // sans bar de progression.
uint crc = CRC32.GetCrc32( "nom_de_fichier.ext" , true , System.Windows.forms.ProgressBar  ) //avec bar de progression

/*   NOTE : Utilisez cette fonction dans un thread , ca évitera de "figer" votre appli    */

Dans le zip j'ai inclus ma source C# et celle que j ai ecris en C++ (avec la classe de l'auteur original dedans).


Source

  • using System;
  • using System.Windows.Forms;
  • using System.IO;
  • //************************************************************
  • // CALCUL CRC32 EN C#
  • // 27 janvier 2005 par lunatik
  • // Base sur le code C++ de Capa6T
  • // http://www.cppfrance.com/code.aspx?ID=24351
  • // (et mon site -> http://www.kawaiistudio.no-ip.com/lunatikv6 ^^ )
  • // Merci à Xya et cbeyls de csharpfr.com pour leurs conseils !
  • //************************************************************
  • namespace CRC32
  • {
  • public class CRC32
  • {
  • /// <summary>
  • /// Calculer un CRC32 ( Cyclic Redundancy Check ) d'un fichier.
  • /// </summary>
  • /// <param name="filePath">Chemin du fichier.</param>
  • /// <param name="enableProgress">Si enableProgress est vrai , la progression du calcul sera affiche
  • /// dans le System.Windows.Forms.ProgressBar que vous aurez definit en 3eme argument de cette fonction</param>
  • /// <param name="pBar">Le ProgressBar ou sera affiche la progression ( si enableProgress est "faux" mettez "null" ).</param>
  • /// <returns>Le CRC sous forme de uint ( 32bit unsigned ) , utilisez crc32.ToString("X"); pour l'affichage
  • /// hexadecimal.</returns>
  • public static uint GetCrc32( string filePath , bool enableProgress ,ProgressBar pBar )
  • {
  • int myTimer = Environment.TickCount;
  • //on initialise un filestream.
  • FileStream myStream = new FileStream( filePath , FileMode.Open , FileAccess.Read );
  • //On stock la taille du fichier.
  • long fileSize = myStream.Length;
  • if( enableProgress ) pBar.Maximum = ( int )fileSize + 2 ;
  • //quelques variables...
  • uint[] LookUpTable = new long[ 256 ];
  • uint poly = 0xEDB88320;
  • uint crc32 = 0;
  • // *NOTE* , je n'utilise pas le meme polynome que celui utilise dans la source C++ dont je me suis inspire
  • // ni le meme algorithme pour generer la Table , mais au final la table est strictement la meme. ^^
  • uint val;
  • //Generation de la Table
  • for( int i = 0 ; i <= 0xFF ; ++i)
  • {
  • val = i;
  • for( int j = 8 ; j > 0 ; --j )
  • {
  • //Capa6T , dans sa source faisait une comparaison booleene
  • // en calculant val & 1 qui donne 1 ou 0 donc true ou false en C++
  • //or en C# on ne peut plus utiliser 1 et 0 (ni -1 d ailleurs) pour faire une comparaison booleene
  • // ** c etait juste une petite note ^^ **
  • if( ( val & 1 ) == 1 )
  • {
  • val = ( val >> 1 ) ^ poly ; // <-- la j'ai un peu compresse l equation, mais ca passe hehe : )
  • }
  • else
  • val >>= 1 ;
  • }
  • LookUpTable[ i ] = val; // on stock le resultat dans notre table.
  • }
  • /* si vous voulez voir a quoi ressemble la table.
  • *
  • *string table = "";
  • *for( int z = 0 ; z <= 0xFF / 3 ; )
  • *{
  • * table += "0x" + LookUpTable[ z ].ToString("X");
  • * table += " , 0x" + LookUpTable[ z+1 ].ToString("X");
  • * table += " , 0x" + LookUpTable[ z+2 ].ToString("X") + "\n";
  • * z+=3;
  • *}
  • *MessageBox.Show( table );
  • */
  • //on va lire le fichier par block de 4096 byte (4k) pour eviter un surchargement de memoire.
  • //NOTE : cette partie du code à été modifiée, utilisons la méthode de cbeyls
  • //, plus simple , pratique et econome ( mieux quoi ... ^^" )
  • byte[] byteArray = new byte[ 4096 ];
  • int readBytes;
  • crc32 = 0xFFFFFFFF;
  • while( ( readBytes = myStream.Read( byteArray , 0 , 4096 ) ) != 0 )
  • {
  • for( int y = 0 ; y < readBytes ; ++y)
  • {
  • //maintenant voici le tit bout de code qui vient de la source de Capa6T
  • //qui genere un CRC32 avec notre Table generee precedement.
  • crc32 = ( crc32 >> 8 ) ^ LookUpTable[ ( crc32 & 0xFF ) ^ byteArray[ y ] ];
  • }
  • if( enableProgress ) pBar.Value = offset ;
  • }
  • //fermeture du stream
  • myStream.Close();
  • int mySecondTimer = Environment.TickCount; //ca c'est si vous voulez connaitre le temps
  • int ms = mySecondTimer - myTimer; //de calcul exact en m.seconds.
  • //MessageBox.Show( "Le CRC32 a ete calcule en "+ ms.ToString() + " Millisecondes.","Infos");
  • return crc32^0xFFFFFFFF;
  • }
  • }
  • }
using System;
using System.Windows.Forms;
using System.IO;

		//************************************************************
		//			CALCUL CRC32 EN C#	
		//		           27 janvier 2005 par lunatik
		//		 Base sur le code C++ de Capa6T
		//	      http://www.cppfrance.com/code.aspx?ID=24351
		//	(et mon site -> http://www.kawaiistudio.no-ip.com/lunatikv6 ^^ )
		//	Merci à Xya et cbeyls de csharpfr.com pour leurs conseils !
		//************************************************************

namespace CRC32
{
	public class CRC32
	{
		/// <summary>
		/// Calculer un CRC32 ( Cyclic Redundancy Check ) d'un fichier.
		/// </summary>
		/// <param name="filePath">Chemin du fichier.</param>
		/// <param name="enableProgress">Si enableProgress est vrai , la progression du calcul sera affiche
		/// dans le System.Windows.Forms.ProgressBar que vous aurez definit en 3eme argument de cette fonction</param>
		/// <param name="pBar">Le ProgressBar ou sera affiche la progression ( si enableProgress est "faux" mettez "null" ).</param>
		/// <returns>Le CRC sous forme de uint ( 32bit unsigned ) , utilisez crc32.ToString("X"); pour l'affichage
		/// hexadecimal.</returns>
		public static uint GetCrc32( string filePath , bool enableProgress ,ProgressBar pBar )
		{
			int myTimer = Environment.TickCount;
			//on initialise un filestream.
			FileStream myStream = new FileStream( filePath , FileMode.Open , FileAccess.Read );
			//On stock la taille du fichier.
			long fileSize = myStream.Length;
			if( enableProgress ) pBar.Maximum = ( int )fileSize + 2 ;

			//quelques variables...
			uint[]	LookUpTable	= new long[ 256 ];
			uint 	poly		= 0xEDB88320;
			uint 	crc32		= 0;
			//   *NOTE* , je n'utilise pas le meme polynome que celui utilise dans la source C++ dont je me suis inspire
			//   ni le meme algorithme pour generer la Table , mais au final la table est strictement la meme. ^^

			uint val;
			//Generation de la Table
			for( int i = 0 ; i <= 0xFF ; ++i)
			{
				val = i;
				for( int j = 8 ; j > 0 ; --j )
				{
					//Capa6T , dans sa source faisait une comparaison booleene 
					// en calculant    val & 1 qui donne 1 ou 0  donc true ou false en C++
					//or en C# on ne peut plus utiliser 1 et 0 (ni -1 d ailleurs) pour faire une comparaison booleene
					// ** c etait juste une petite note ^^ **
					if( ( val & 1 ) == 1 )
					{
						val = ( val >> 1 ) ^ poly ; 	// <-- la j'ai un peu compresse l equation, mais ca passe hehe : )
					}
					else
						val >>= 1 ;						
				}
				LookUpTable[ i ] = val; // on stock le resultat dans notre table. 
			}

			/* si vous voulez voir a quoi ressemble la table.
			 *
			 *string table = "";
			 *for( int z = 0 ; z <= 0xFF / 3 ; )
			 *{
			 *	table += "0x" + LookUpTable[ z ].ToString("X");
			 *	table += " , 0x"  + LookUpTable[ z+1 ].ToString("X");
			 *	table += " , 0x"  + LookUpTable[ z+2 ].ToString("X") + "\n";
			 *	z+=3;
			 *}
			 *MessageBox.Show( table );
			 */

			//on va lire le fichier par block de 4096 byte (4k) pour eviter un surchargement de memoire.
			//NOTE : cette partie du code à été modifiée, utilisons la méthode de cbeyls 
			//, plus simple , pratique et econome ( mieux quoi ... ^^" )
			byte[] byteArray = new byte[ 4096 ];
			int readBytes;
			crc32 = 0xFFFFFFFF;
			
			while( ( readBytes = myStream.Read( byteArray , 0 , 4096 ) ) != 0 )
			{
				for( int y = 0 ; y < readBytes ; ++y)
				{
					//maintenant voici le tit bout de code qui vient de la source de Capa6T
					//qui genere un CRC32 avec notre Table generee precedement.
					crc32 = ( crc32 >> 8 ) ^ LookUpTable[ ( crc32 & 0xFF ) ^ byteArray[ y ] ];
				}
				if( enableProgress ) pBar.Value = offset ;
			}
			//fermeture du stream
			myStream.Close();
            
			int mySecondTimer = Environment.TickCount;  //ca c'est si vous voulez connaitre le temps
			int ms = mySecondTimer - myTimer;				//de calcul exact en m.seconds.
			//MessageBox.Show( "Le CRC32 a ete calcule en "+ ms.ToString() + " Millisecondes.","Infos");

			return crc32^0xFFFFFFFF;
		}
	}
}

 Conclusion

Ce code n'est certainement pas le plus rapide pour effectuer un tel calcul ,
si vous avez des idées pour l 'améliorer , je suis preneur !! ^^

*NOTE* -> le temps approximatif prevu a été calculé , par rapport aux résultats que donnait mon programme
sur mon ordi (càd un athlon1800+ avec une vieille ddr 166 , le dur pas defragmenté ,  2~3 visual studio plus quelques applis qui tournaient par derriere).
J'aimerais , si certains d entre vous ont le temps , avoir les résultats sur des ordi moins puissants .
un grand merci a Capa6T pour son algo crc32 ( j en ai cherché un  pendant longtemps ^^ )

Je vous rappele qu'il est déconseillé d'utiliser le crc32 en matiere de protection , pour un usage professionel  utilisez plutot un hash MD5 (par ex celui dispo dans la librairie CsLib de ce site ^^ )

 Fichier Zip

Les Membres Club peuvent télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !
  • App.icoTélécharger ce fichier [Réservé aux membres club]Voir ce fichier1 078 octets
  • AssemblyInfo.csTélécharger ce fichier [Réservé aux membres club]Voir ce fichier2 426 octets
  • CRC32.exeTélécharger ce fichier [Réservé aux membres club]10 240 octets
  • CRC32.pdbTélécharger ce fichier [Réservé aux membres club]19 968 octets
  • CRC32.csTélécharger ce fichier [Réservé aux membres club]Voir ce fichier4 498 octets
  • CRC32.csprojTélécharger ce fichier [Réservé aux membres club]Voir ce fichier4 541 octets
  • CRC32.csproj.userTélécharger ce fichier [Réservé aux membres club]Voir ce fichier1 772 octets
  • CRC32.slnTélécharger ce fichier [Réservé aux membres club]Voir ce fichier906 octets
  • CRC32.suoTélécharger ce fichier [Réservé aux membres club]7 680 octets
  • Form1.csTélécharger ce fichier [Réservé aux membres club]Voir ce fichier6 947 octets
  • Form1.resxTélécharger ce fichier [Réservé aux membres club]Voir ce fichier5 315 octets
  • CRC32.exeTélécharger ce fichier [Réservé aux membres club]10 240 octets
  • CRC32.exe.incrTélécharger ce fichier [Réservé aux membres club]1 886 octets
  • CRC32.Form1.resourcesTélécharger ce fichier [Réservé aux membres club]324 octets
  • CRC32.pdbTélécharger ce fichier [Réservé aux membres club]19 968 octets
  • CRC32.projdataTélécharger ce fichier [Réservé aux membres club]10 376 octets
  • CRC32.ncbTélécharger ce fichier [Réservé aux membres club]52 224 octets
  • CRC32.slnTélécharger ce fichier [Réservé aux membres club]Voir ce fichier910 octets
  • CRC32.suoTélécharger ce fichier [Réservé aux membres club]9 216 octets
  • CRC32.vcprojTélécharger ce fichier [Réservé aux membres club]3 072 octets
  • crc32main.cppTélécharger ce fichier [Réservé aux membres club]Voir ce fichier6 036 octets
  • crc32rc.apsTélécharger ce fichier [Réservé aux membres club]33 908 octets
  • crc32rc.rcTélécharger ce fichier [Réservé aux membres club]Voir ce fichier2 447 octets
  • BuildLog.htmTélécharger ce fichier [Réservé aux membres club]Voir ce fichier6 230 octets
  • CRC32.exeTélécharger ce fichier [Réservé aux membres club]114 688 octets
  • CRC32.ilkTélécharger ce fichier [Réservé aux membres club]431 124 octets
  • CRC32.pdbTélécharger ce fichier [Réservé aux membres club]445 440 octets
  • crc32main.objTélécharger ce fichier [Réservé aux membres club]19 966 octets
  • crc32rc.resTélécharger ce fichier [Réservé aux membres club]548 octets
  • vc70.idbTélécharger ce fichier [Réservé aux membres club]330 752 octets
  • vc70.pdbTélécharger ce fichier [Réservé aux membres club]94 208 octets
  • resource.hTélécharger ce fichier [Réservé aux membres club]Voir ce fichier703 octets

Télécharger le zip


 Historique

27 janvier 2005 21:14:16 :
ajout d un screenshot
27 janvier 2005 21:55:35 :
modif main.cpp dans le zip (pas important mais bon ... ^^ )
28 janvier 2005 16:04:31 :
j'avais mis "string" au lieu de "long" dans la presentation , désolé : )
02 février 2005 22:17:48 :
rectif. long -> uint pour plus de performances , si vous avez d autres idées , n'hésitez pas !!
07 février 2005 21:03:48 :
Modification de la méthode de lecture du stream ( voir message de cbeyls plus bas )

 Sources du même auteur

Source avec Zip Source .NET (Dotnet) FILTRES ET MANIPULATION D'IMAGES EN UTILISANT LOCKBITS ET DE...

 Sources de la même categorie

RECHERCHE DE DEUX SOUS ENSEMBLE DONT LES SOMMES DES ÉLÈMENTS... par deadhand
Source avec Zip Source avec une capture Source .NET (Dotnet) METHODE GRAPHIQUE EN PROGRAMMATION LINÉAIRE par vindos
Source avec Zip Source avec une capture Source .NET (Dotnet) RECTANGLES par krissssss
Source avec Zip Source avec une capture SODOKU MUSING (PERMUTATION & SODOKU) par krissssss
Source avec Zip Source avec une capture Source .NET (Dotnet) ANALYSEUR LEXICAL ET SYNTAXIQUE DES FORMULES PROPOSITIONNELL... par boutemine

 Sources en rapport avec celle ci

Source .NET (Dotnet) CALCUL DU CRC32 A TRAVERS UN SYSTEM.IO.STREAM par Vince_02
Source avec Zip Source avec une capture Source .NET (Dotnet) CRC32 COMPATIBLE WINZIP ET WINRAR PAR DÉFAUT (GÉNÉRALISATION... par BaFM

Commentaires et avis

Commentaire de Xya le 31/01/2005 00:07:00

Tu pourrais améliorer les performances en remplaçant tous les longs (64 bits) par des uints (32 bits), comme le calcul d'un crc32 n'utilise que 32 bits, sur un fichier de 450 Mo avec des longs ca me met 8 secondes contre 5 secondes avec des uints.

Commentaire de li9 le 02/02/2005 22:14:03

Salut Xya , merci beaucoup pour ton commentaire.
Effectivement, en C# un long est un 64bit signed,
j'aurais dû utiliser un uint .
Capa6T , dans sa source, utilisait un DWORD (32bit unsigned) et comme un LONG en C++ est un 32bit signed,  j ai pensé qu'en C# ça aurait été pareil ^^".
petite note : j'ai utilisé une valeur signed pendant la conversion parce que j avais quelque problemes lors de la génération de la table.
Merci pour ta remarque , je vais changer ces longs en uints ^^ .

Commentaire de cbeyls le 04/02/2005 05:48:40

Les ToString() pendant la création de la lookup table, ça me paraît totalement farfelu!

De plus, tu pourrais générer la table uniquement la première fois que la fonction est appelée et ensuite la laisser en mémoire, pour gagner un peu de temps lors des appels suivants à la méthode.

Quant à la lecture dans le fichier, tu peux la faire directement avec

int bytesLus = myStream.Read( byteArray , 0 , 4096 );

sans calculer la taille restate auparavant. La méthode Read renvoie le nombre de bytes effectivement lus. Attention, elle peut très bien en renvoyer moins que la taille du buffer même si on n'est pas à la fin du fichier! (même si c'est très improbable). C'est écrit dans la documentation du SDK:

Stream.Read: Valeur de retour: Nombre total d'octets lus dans la mémoire tampon. Cela peut être inférieur au nombre d'octets demandé si ce nombre n'est pas actuellement disponible ou égal à zéro (0) si la fin du flux a été atteinte.

Commentaire de li9 le 04/02/2005 10:41:41

Hello cbeyls , merci pour a toi aussi pour ton commentaire !

Les ToString() ne sont pas du tout pendant la création de la table !! J'ai bien ecris en commentaire "//Si vous voulez voir à quoi ressemble la table...",  le code entre les /* et */  sert juste a afficher un MessageBox avec la table dans un string , thats all ^^.
Et j'evite justement un "EndOfFileException" en verifiant que le reste du fichier a lire n'est pas plus petit que 4096bytes !
Dans ma premiere boucle je li par block de 4k tant que l'offset et la taille du fichier ne sont pas egal je verifie ensuite que ( File.Length - Offset ) >= 4096  si ce n'est pas le cas je ne lis que File.Length - Offset au lieu de 4096, ^^ ca evite de lire plus que ce que le fichier ne contient !!

C'est vrai pour la generation de la table , j ai même pensé a enlever le code et mettre une table deja générée (ca aurait ete beaucoup moins marrant ^^ ) , mais je me suis finalement demandé si ca valait le coup etant donné que la table doit se générer en quelque millisecondes...
Je vais regarder ca.

Merci beaucoup
++

lunatik

Commentaire de li9 le 04/02/2005 10:43:09

desolé pour les fautes je me reveille tout juste ^^"

Commentaire de cbeyls le 04/02/2005 15:27:01

Pour les ToString(), effectivement je n'avais pas fait attention au fait que la portion de code est commentée :)

Par contre, pour la lecture, je comprend ce que tu veux faire mais je t'explique que ce n'est pas la bonne façon de faire. Si tu demandes à lire 4096 bytes dans un Stream, tu peux très bien te retrouver par exemple avec 4090 bytes même si tu en as demandé 4096 et qu'il reste plus de 4096 bytes à lire, il faut donc toujours tester quel est le nombre de bytes que la fonction Read renvoie. Je posterai le code correct plus tard dans la journée.

Commentaire de cbeyls le 04/02/2005 19:18:25

Pour la lecture, ceci devrait suffire et plus besoin des variables offset, ni diff, ni fileSize:

            // Read the Stream to its end and fill the buffer
            while( ( readBytes = stream.Read(buffer, 0, BUFFER_SIZE) ) != 0 )
            {                
                // Compute the new CRC32 for the current buffer content
                for(int i=0; i < readBytes; ++i)
                {
                    crc32 = ( crc32 >> 8 ) ^ lookupTable[ ( crc32 & 0xFF ) ^ buffer[i] ];
                }
            }

Commentaire de cbeyls le 04/02/2005 19:26:14

petites précisions:
- j'ai donc déclaré readBytes en tant que int juste avant cette boucle.
- BUFFER_SIZE est une constante qui est la taille du buffer, dans ton exemple c'était 4096 mais personnellement je l'ai augmentée à 16384.

Commentaire de li9 le 05/02/2005 15:07:58

Effectivement grace à ta méthode j'éconimise 3 ou 4 variables ! et ca marche tres bien : )
Grace a vos conseils le calcul se fait presque 2 fois plus rapidement qu'avant , terrible ^^v
Si vous avez d autre bons conseils comme ceux là n'hésitez pas héhé.

Merci beaucoup!

Commentaire de Capa6T le 07/02/2005 15:31:38

Salut li9,
Je passait pas hasard sur le code csharp car celà commence a me démanger....il faut que je m'y mette... et je tombe avec plaisir sur ton code.
Il a très bien évolué en terme de performance d'après ce que je peut lire. (lol je n'hésiterais pas a te confier d'autres sources)
C'est tout bonnement génial pour moi qui voulait me faire une idée du C# car je l'ai vu naître en C ce code (inspiré par un tiers...je ne l'ai pas inventé non plus).
Voilà c'était juste un petit commentaire peu constructif mais juste sympathique...
Merci (j'y retourne et je me plonge dedans pour comprendre un peu l'utilisation et l'utilité du C#)

Commentaire de Xya le 07/02/2005 18:31:39

Si tu cherches encore à optimiser ton code je te conseille de jeter un coup d'oeil à CLR Profiler (http://www.microsoft.com/downloads/details.aspx?FamilyID=86ce6052-d7f4-4aeb-9b7a-94635beebdda&DisplayLang=en) et à NProf (http://nprof.sourceforge.net/Site/SiteHomeNews.html). C'est vrai que ces deux outils marchent mieux pour dépister ce qui pourrait être amélioré sur un plus grand nombre de méthodes, mais cela permet de repérer les erreurs bêtes (par exemple allouer de la mémoire dans une boucle, ou utiliser plusieurs fois String.Replace sur le contenu d'un fichier...).

Commentaire de li9 le 08/02/2005 01:20:17

Salut Capa6T ça fait plaisir de voir un message de ta part ici !
Je suis content que ça te plaise et que ça puisse te donner une bonne idée du C# ( Tu verras c'est d'une simplicité enfantine comparé au c++ lol ^^" ) .
Je viens de modifier la source ( mais pas encore le zip désolé ... ) j'ai utilisé la methode de cbeyls pour la lecture et utilisé des uint a la place de mes vieux longs ( qui sont désormais 64bits en C# lol fait gaffe ^^ ) merci a Xya.
Dailleurs, Xya , j'ai essayé le clr profiler , c'est terrible mais l'espece de graphique qu'il te sort le machin mdrrrr je vais regarder ça de plus pres quand je serais plus frais lol , en tout cas merci beaucoup !
++

lunatik

Commentaire de cbeyls le 09/02/2005 04:53:32

Hello, c'est encore moi. J'ai vu que tu as changé ta source, c'est sympa. Mais j'ai encore quelques remarques.

En fait j'ai écrit une classe optimisée pour mon usage personnel en m'inspirant de ton code et d'une source en C (l'algorithme est le même, apparemment, c'est le plus rapide, en tous cas j'ai pas trouvé mieux), j'ai enlevé la progressBar, mis quelques commentaires en anglais et j'ai utilisé un Stream en entrée au lieu d'un nom de fichier. C'est un bout de ce code que je t'ai copié-collé.

Seulement, comme toi tu utilises une progressBar, il y a quelques petites choses que tu devrais changer:

1) Tout d'abord d'un point de vue purement esthétique et pratique, je ne vois pas l'intérêt du 2e paramètre, le booléen enableProgress. Si j'étais toi, je l'enlèverais et je demanderais à l'utilisateur d'attribuer la valeur null à l'argument pBar s'il ne souhaite pas de progressBar. Ensuite au lieu de tester
if(enableProgress)
tu testerais
if(pBar != null)

2) Je t'ai dit que tu n'aurais plus besoin de la variable offset, mais tu l'emploies toujours pour la progressBar. Il y a toujours moyen d'utiliser la progressBar sans cette variable, mais il faut un peu adapter ton code. Au début, remplace

long fileSize = myStream.Length;
if( enableProgress ) pBar.Maximum = ( int )fileSize + 2 ;

par

if( pBar != null )
{
   pBar.Minimum = 0;
   pBar.Maximum = (int)myStream.Length;
}

J'avoue aussi que je n'ai pas compris pourquoi tu faisais +2, normalement la taille du fichier devrait suffire. Ensuite, dans le code de la boucle, remplace:

if( enableProgress ) pBar.Value = offset ;

par

if( pBar != null )
{
   pBar.Value += readBytes;
   Application.DoEvents();
}

Le Application.DoEvents() c'est pour éviter que ton interface graphique ne plante complètement pendant le calcul du CRC32, et continue à réagir aux événements de la souris et à rester "vivante". Ceci parce que tu effectues le calcul du CRC32 dans le cadre du Thread qui s'occupe de l'affichage. Si tu n'appelles pas DoEvents() ton application est incapable de réagir à la souris ou au clic sur un bouton pendant tout le calcul ! Si tu veux éviter que quelqu'un clique sur un bouton pendant le calcul, grise les boutons ou change le pointeur en sablier avant le calcul et revient à la normale après, mais laisse le DoEvents(), ça évitera à Windows de croire que le programme est planté si tu t'acharnes à la souris dessus.

3) Dernière remarque, mais cela je suppose que tu le sais déjà, le calcul est plus rapide lorsque le code est compilé en mode Release par rapport au mode Debug.

Commentaire de cbeyls le 09/02/2005 04:59:22

J'ai encore oublié un petit détail :)

if( pBar != null )
{
   pBar.Minimum = 0;
   pBar.Maximum = (int)myStream.Length;
   pBar.Value = 0;
}

Faut mettre la valeur de la progressBar à zéro au début, voilà ;)
J'espère que tu as tout pigé, si jamais tu as des questions, n'hésite pas à me contacter.

Commentaire de li9 le 09/02/2005 20:37:47

Salut cbeyls ,
merci beaucoup pour tes messages,
Tout ça améliore carement la fonction,
( pour le booleen en 2nd argument tu as entierement raison , c'est une étourderie de ma part ^^" ).
En fait c'est vrai qu'on a pas à faire filesize +2 lol,
c'est pendant que j ecrivais la fonction , la premiere fois j ai eu des problèmes avec la progressebar donc j ai rajouté +2 au max size ^^" ..... mais là c'est complètement inutile.
et pour éviter que l appli se freeze je mettais tout ça dans un thread , mais dans la fonction directement c'est beaucoup mieux !
et si effectivement on a là , l'algo le plus rapide pour le moment , c'est grâce à Capa6T ^^ , moi j'ai fait que copier lol...

Merci encore ,
++

lunatik

Commentaire de cbeyls le 10/02/2005 01:30:25

> et pour éviter que l appli se freeze je mettais tout ça dans un thread , mais dans la fonction directement c'est beaucoup mieux !

En fait c'est mieux de le mettre dans un 2e Thread, mais dans les sources que j'ai téléchargées ici, tu fais tout dans le même. Et puis, quand tu crées un 2e Thread, il y a un problème: seul le Thread de l'interface graphique est capable de modifier l'interface graphique, donc dans un 2e Thread, la progressBar ne bougerais pas (même si je n'ai pas testé mais c'est toujours le même problème avec les interfaces graphiques WinForms). Quand un 2e Thread doit modifier l'interface graphique, il faut utiliser un delegate et différer son exécution mais bon, on va dire que c'est hors sujet! L'avantage majeur d'utiliser un 2e Thread c'est que, quand l'utilisateur clique sur la croix pour fermer le programme, le Thread graphique peut dire au 2e: Stop! Autrement dit, Thread.Abort()
Ici ce n'est pas le cas, tout se fait dans le même Thread, résultat, une fois que le calcul du CRC est commencé, impossible de l'arrêter comme ça. Alors pour l'arrêter, on pourrait ajouter une méthode Stop() à la classe, qui fait passer un booléen à false et qui permet de sortir de la boucle qui calcule le CRC. C'est juste une suggestion.

La progressBar pose un autre problème: vu la façon dont on l'utilise, la taille du fichier en bytes est passée à MaxValue qui est un int. Ca limite l'utilisation à des fichiers de maximum 2 exposant 31 bytes, autrement dit 2 gigabytes. Pour les fichiers plus gros, ça ne fonctionne pas avec cette méthode.

J'ai pour principe de toujours séparer l'interface graphique du reste du code, donc moi la progressBar je l'ai virée et je n'ai donc pas tous ces problèmes, même s'il est vrai que ça pourrait être bien de connaître le statut de la progression, mais alors via d'autres moyens comme par exemple enregistrer un callback sous la forme d'une fonction qui prend en paramètre une valeur qui représente un pourcentage de progression, par exemple.

Niveau performances, j'ai fait des tests avec plusieurs fichiers sur différents disques durs, et il me semble que la valeur idéale pour le buffer de lecture est de 16384 bytes. Ca ne va pas plus vite que 4096 bytes, mais ça consomme un peu moins de CPU. Au-delà, ça commence à ralentir donc je ne conseille pas.

 Ajouter un commentaire




Nos sponsors


Sondage...

Comparez les prix

CalendriCode

Février 2010
LMMJVSD
1234567
891011121314
15161718192021
22232425262728

Consulter la suite du CalendriCode

 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 0,530 sec (3)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales