Fragmenteur / reconstructeur de fichiers [source c]

Soyez le premier à donner votre avis sur cette source.

Vue 5 337 fois - Téléchargée 193 fois

Description

Voici une source permettant de fragmenter un fichier en plusieurs autre.
J'ai fais cette source pour le transport sur disquette et également pour pouvoir télécharger un fichier en plusieurs fois.

Pour faire l'acquisition de la taille du fichier j'ai tout simplement utilisé fseek() pour connaitre la position dans le fichier du dernier octet.
N'existe t'il pas une fonction ?

J'ai également un autre petit problème c'est pour convertir un int en chaîne de caractère.
J'utilise la fonction fcvt(), n'existe t'il pas une fonction ainsi pour avoir une meilleure porabilité ?

Un truc, j'ai pas limité la taille du buffer entre le fichier source et le fichier de destination car je n'ai pas de problème de disponibilté de mémoire.
De toute façon je fais des fragments de 10 Mo maximum.

Source / Exemple :


/********************************************************/
/*														*/
/*		  FRAGMENTEUR/DEFRAGMENTEUR DE FICHIERS			*/
/*														*/
/********************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define FRAGMENTER		1
#define MAX 			20

/* prototypes */

int acquisition (char *filename, long *fragsize, int *erasefrag);

int filefrag (char *filename, long fragsize);
int fbuild (char *filename, int erasefrag);

long fsize (char *filename);
void fname (char *filename, char *newname, int nb);

/* main() */

int main (void)
{
	int choix;
	int erase;
	long fragsize;
	char filename[MAX];

	choix = acquisition(filename, &fragsize, &erase);

	if(choix == FRAGMENTER)
		filefrag(filename, fragsize);
	else
		fbuild(filename, erase);

	/* fin du programmme */

	fflush(stdin);
	getchar();
	return 0;
}

/******** acquisition des données pour le programme *********/

int acquisition (char *filename, long *fragsize, int *erase)
{
	int choix;

	/* choix = fragment/reconstruire */

	do
	{
		printf("\n\n1=fragmenter, 2=reconstruire : ");
		scanf("%d",&choix);
	}
	while(choix < 1 || choix > 2);

	/* acquisition des données nécessaires */

	fflush(stdin);

	printf("\nNom du fichier : ");
	gets(filename);

	if(choix == FRAGMENTER)
	{
		printf("\nEntrez la taille en Ko des fragments (1 Mo = 1024 Ko) : ");
		scanf("%ld", fragsize);

  • fragsize *= 1024; /* taille en octets */
} else do { printf("\nVoulez vous effacer les fragments (O/N) ?"); switch( getchar() ) { case 'o' : case 'O' : *erase = 1; break; case 'n' : case 'N' : *erase = 0; break; default : *erase = -1; } } while(*erase == -1); return choix; } /* ----------------------------------------------------------------------- fonction : int filefrag (char *filename, long fragsize) description : filefrag() permet de fragmenter un fichier en plusieurs autre d'une taille prédéfinie. val envoyées : - filename = nom du fichier à fragmenter. - fragsize = taille de chaque fragment en octets. val renvoyées : - si succès : 1 - si erreur : 0 portabilité : dos uniquement. (à cause de fcvt() dans fname()) exemple : filefrag("test.txt", 1024); ici on fragmente test.txt en plusieurs fichiers de 1 Ko (sauf le dernier fragment). La taille du dernier fragment varie en fonction du nombre d'octets de donnés qu'il reste à copier. ------------------------------------------------------------------- */ int filefrag (char *filename, long fragsize) { FILE *fsource; FILE *fdest; char *buffer; char filefrag[MAX]; fpos_t taille; fpos_t sizetemp; int nb = 0; /* passage à la ligne */ puts(""); /* détection de la taille du fichier source */ taille = fsize(filename); /* ouverture du fichier à fragmenter */ if( (fsource = fopen(filename,"rb")) == NULL) { fprintf(stderr, "Fichier %s inexistant !", filename); return 0; } /* fragmentation du fichier */ buffer = malloc(fragsize); while(taille > 0) { if(taille <= fragsize) sizetemp = taille; else sizetemp = fragsize; fname(filename ,filefrag, ++nb); puts(filefrag); fdest = fopen(filefrag,"wb"); fread(buffer, sizetemp, 1, fsource); fwrite(buffer, sizetemp, 1, fdest); fclose(fdest); taille -= sizetemp; } free(buffer); /* fermeture du fichier source */ fclose(fsource); /* fin de la fragmentation */ printf("\n%s fragmente en %d fichiers...", filename, nb); return 1; } /* ----------------------------------------------------------------------- fonction : void fname (char *filename, char *newname, int nb) description : fname() permet de générer un nom de fichier (newname) identique à filename mais sans extension et suivi d'un numéro nb val envoyées : - filename = nom du fichier d'origine. - newname = nouveau nom de fichier - nb = numéro à ajouter à la suite du nom val renvoyées : void portabilité : dos uniquement. (à cause de fcvt()) exemple : fname("test.txt", tab, 1); ici on obtient dans tab[] = "test1". ------------------------------------------------------------------- */ void fname (char *filename, char *newname, int nb) { register int k = 0; char temp[MAX]; /* même nom sans l'extension */ while(filename[k] != '.') newname[k] = filename[k++]; newname[k] = '\0'; /* on y ajoute le nb à la suite */ itoa(nb, temp, 10); strcat(newname, temp); } /* ----------------------------------------------------------------------- fonction : long fsize (char *filename) description : fsize permet de déterminer la taille en octets d'un fichier. val envoyées : - filename = nom du fichier à analyser. val renvoyées : - si succès : taille du fichier en octets - si erreur : -1 portabilité : dos, unix, c ansi, c++ seul exemple : taille = fsize("test.txt"); ici on stocke dans taille la taille en octets du fichier test.txt. ------------------------------------------------------------------- */ long fsize (char *filename) { FILE *fp; long taille; /* ouverture du fichier */ if( (fp = fopen(filename,"rb")) == NULL) { fprintf(stderr, "Fichier %s inexistant !", filename); return -1; } /* détection de la taille du fichier */ fseek(fp, 0, SEEK_END); fgetpos(fp, &taille); /* fermeture du fichier */ fclose(fp); return taille; } /* ----------------------------------------------------------------------- fonction : int fbuild (char *filename, int erase) description : fbuild() permet de reconstruire un fichier qui a été fragmenté à l'aide de filefrag(). val envoyées : - filename = nom du fichier à reconstruire. - erase = booléen qui détermine si on efface les fragments après reconxtruction. val renvoyées : - si succès : 1 - si erreur : 0 portabilité : dos uniquement. (à cause de fcvt() dans fname()) exemple : fbuild("test.txt", 1); on reconstruit le fichier test.txt en effaçant les fragments (test1, test2 ...) ------------------------------------------------------------------- */ int fbuild (char *filename, int erase) { FILE *fsource; FILE *fdest; char *buffer; char filefrag[MAX]; long fragsize; int nb = 1; /* passage à la ligne */ puts(""); /* ouverture du fichier de destination */ if( (fdest = fopen(filename,"wb")) == NULL) { fprintf(stderr, "Erreur de creation du fichier %s !", filename); return 0; } /* détection taille des/du fragment(s) */ fname(filename ,filefrag, nb); fragsize = fsize(filefrag); /* allocation de la mem necessaire pour le buffer */ buffer = malloc(fragsize); /* remplissage du fichier de destination */ while( (fsource = fopen(filefrag,"rb")) != NULL ) { puts(filefrag); /* vérif de la taille du fragment */ fclose(fsource); if(fsize(filefrag) != fragsize) fragsize = fsize(filefrag); /* reconstruction fichier */ fsource = fopen(filefrag,"rb"); fread(buffer, fragsize, 1, fsource); fwrite(buffer, fragsize, 1, fdest); fclose(fsource); /* suppression des fragments */ if(erase) remove(filefrag); /* préparation pour le prochain fichier */ fname(filename, filefrag, ++nb); } free(buffer); /* fermeture du fichier de destination */ fclose(fdest); /* fin de la reconstruction */ printf("\nFichier %s reconstruit...", filename); return 1; }

Conclusion :


J'ai essayé de faire au plus simple.

Le pricipal bug, c'est quand il faut entrer 1 ou 2 au moment du choix de la fragmentation ou de la reconstruction.
Si l'on entre un caractère, le programme plante.

Codes Sources

A voir également

Ajouter un commentaire Commentaires
Messages postés
3011
Date d'inscription
jeudi 26 septembre 2002
Statut
Membre
Dernière intervention
27 novembre 2004
8
bien sur que fflush est portable puisqu'elle est definie dans le standard ansi

c'est fflush sur un input stream qui n'a pas de comportement standard, ca marche pas, ca peux planté, et vidé stdin c'est aussi stupide que de vider le tampon d'un FILE* que tu est en train de lire


void clear_kb (void)
{
char junk[80];
gets(junk);
}

cette fonction est dans le meme esprit, il vide stdin, apres tu sera meme pas ce que tu lit suivant l'etat du buffer

si tu ve sauter un '\n', il n'y a que cette solution qui soit correcte

while( c=fgets(stdin) != '\n' && c != EOF);
Messages postés
12
Date d'inscription
samedi 31 juillet 2004
Statut
Membre
Dernière intervention
11 août 2004

djl>

d'après l'aide de Borland, fflush() est tout à fait portable,
voici une fonction qui te permet de faire la même chose :

void clear_kb (void)
{
char junk[80];
gets(junk);
}

ps : j'ai testé ton code sa marche mais cette fonction mieux adapté, car on n'attend pas de valeur particulière.
Messages postés
3011
Date d'inscription
jeudi 26 septembre 2002
Statut
Membre
Dernière intervention
27 novembre 2004
8
quand ta un '\n' qui traine dans stdin, saute le

mets while( c=fgets(stdin) != '\n' && c != EOF); a la place de fflush(stdin)

fflush sur stdin à un effet indeterminé, c'est pas portable, dangereux et illogique
Messages postés
12
Date d'inscription
samedi 31 juillet 2004
Statut
Membre
Dernière intervention
11 août 2004

Pour le cast du malloc tu as raison, en ce qui concerne les fflush(stdin) essaye de les enlever et tu vas voir sa marche pas des masses.

Donc j'ai enlevé les cast des malloc().

Merci djl.
Messages postés
12
Date d'inscription
samedi 31 juillet 2004
Statut
Membre
Dernière intervention
11 août 2004

Bin en faite le fflush(stdin) j'ai pas eut trop le choix.
Pour le dernier surtout.
parce qu'en faite au lieu demettre conio.h, pour mettre un getch(), j'ai mis un getchar() qui attend que tu appuie sur enter.

Le problème c'est que quand il reste des truc dans stdin sa se ferme sans que tu appuie sur enter.
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.