Ecriture dans un fichier

Fermé
aure2015 Messages postés 93 Date d'inscription dimanche 11 janvier 2009 Statut Membre Dernière intervention 30 mai 2020 - Modifié le 23 janv. 2018 à 15:34
[Dal] Messages postés 6194 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 11 octobre 2024 - 24 janv. 2018 à 11:08
Bonjour à tous!

Je vous explique mon petit problème, j'ai une ligne à modifier dans un fichier! Hors malgré mon ouverture r+, ça ne fonctionne pas et je ne comprends pas pourquoi! Ca compile, ça ne me renvoie pas d'erreur mais ça ne modifie pas le fichier comme il devrait! ( Je compile sous Unix).

Merci d'avance!

Voici le code:
void RecupCom( )
{

COMMANDES Com;
FILE *Fichier;
int Taille;

Fichier=fopen("Commandes.dat","rb");
if(Fichier!=NULL)
{
 fread(&Com,sizeof(COMMANDES),1,Fichier);
 while (!feof(Fichier))
 {
  Trace("%s\t%d\n",Com.Nom,Com.Valide);
  fread(&Com,sizeof(COMMANDES),1,Fichier);
 
 }
 fclose(Fichier);

 Fichier=fopen("Commandes.dat","r+");
 fread(&Com,sizeof(COMMANDES),1,Fichier);
 Taille=0;
 
 while (!feof(Fichier))
 {
  
 
  if(Com.Valide==2)
  {
                        // fseek(Fichier,(-sizeof(COMMANDES)),SEEK_CUR)
   if(fseek(Fichier,(Taille*sizeof(COMMANDES)),SEEK_SET)!=0)
    Trace("Erreur");
   Com.Valide=1;
   Trace("Boucle modif");
   if(fwrite(&Com,sizeof(COMMANDES),1,Fichier)<0)
    Trace("Erreur ecriture");
  }
  
  Taille++;
  fread(&Com,sizeof(COMMANDES),1,Fichier);
 }
 Trace("Apres modif\n");
 fclose(Fichier);
 fopen("Commandes.dat","rb");
 fread(&Com,sizeof(COMMANDES),1,Fichier);

 while (!feof(Fichier))
 {
  Trace("%s\t%d\n",Com.Nom,Com.Valide);
  fread(&Com,sizeof(COMMANDES),1,Fichier);
 
 }
 fclose(Fichier);
}
}

A voir également:

2 réponses

[Dal] Messages postés 6194 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 11 octobre 2024 1 092
23 janv. 2018 à 16:14
Salut aure2015,

C'est un peu difficile le programme n'étant pas un exemple complet permettant de tester et je ne comprends pas trop ce qu'est le type COMMANDES, qui a l'air d'être un struct,... cependant il semble que tu lises le contenu d'un fichier binaire dans l'espace mémoire alloué à ce struct, puisque tu spécifies "rb" lorsque tu l'ouvres en lecture.

Par contre, lorsque tu ouvres le fichier en lecture/écriture, tu ne spécifies plus que ton fichier est binaire.

Essaye donc de passer ""r+b" ou "rb+" au lieu de seulement "r+" pour voir si cela arrange les choses :-)


Dal
0
aure2015 Messages postés 93 Date d'inscription dimanche 11 janvier 2009 Statut Membre Dernière intervention 30 mai 2020 5
23 janv. 2018 à 17:59
Je vais remettre des fonctions un peu plus clairement, c'est vrai que ce n'est pas top pour le moment! J'y avais déjà pensé mais rien ne change!

Merci pour l'aide quand même!

Le code:

typedef struct
   { int	Valide;
     char	Nom[50];
   }
COMMANDES;

void Ajout(char *Com)
{


Trace("AjoutCommande commence");
FILE *Fichier;
COMMANDES New;


	
	if ((Fichier = fopen("Commandes.dat","a")) == NULL)
	{
		Trace("Erreur de l'ouverture du Fichier (exit Personnel)");	
		exit(1);
		
	}
	
	strcpy(New.Nom,Com;
	New.Valide=1;
	fwrite(&New,sizeof(COMMANDES),1,Fichier);

	fclose(Fichier);
		
Trace("Sortie Ajout");
}



void Modification ()
{

COMMANDES Com;
FILE *Fichier;
int Taille;


if((Fichier=fopen("Commandes.dat","r+"))!=NULL)
{
	
	Taille=0;
	fflush(stdin);
	fread(&Com,sizeof(COMMANDES),1,Fichier);
	while (!feof(Fichier))
	{
		
		Trace("Avant: %s\t%d\n",Com.Nom,Com.Valide);
		if(Com.Valide==2)
		{
			if(fseek(Fichier,(-sizeof(COMMANDES)),SEEK_CUR)!=0)
				Trace("Erreur");
			
			Com.Valide=1;
			Trace("Boucle modif");
			if(fwrite(&Com,sizeof(COMMANDES),1,Fichier)<=0)
				Trace("Erreur ecriture");

			Trace("Après Modif: %s\t%d\n",Com.Nom,Com.Valide);
		}
		
		Taille++;
		fread(&Com,sizeof(COMMANDES),1,Fichier);
	}
	fclose(Fichier);
}
else
{
	Fichier=fopen("Commandes.dat","w");
	fclose(Fichier);
}
	
}

void AfficherCommande ()
{

COMMANDES Com;
FILE *Fichier;

Fichier=fopen("Commandes.dat","rb");
if(Fichier!=NULL)
{
	fread(&Com,sizeof(COMMANDES),1,Fichier);
	while (!feof(Fichier))
	{
		Trace("%s\t%d\n",Com.Nom,Com.Valide);
		fread(&Com,sizeof(COMMANDES),1,Fichier);
	
	}
	fclose(Fichier);

}
}
0
[Dal] Messages postés 6194 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 11 octobre 2024 1 092
Modifié le 24 janv. 2018 à 11:23
Dans la fonction Ajout(), il manque une parenthèse fermante à strcpy. Je suppose que c'est une erreur de copie-coller, car cette erreur de syntaxe empêcherait la compilation. Aussi, tu ne devrais pas utiliser strcpy(), mais strncpy().

Dans la fonction Modification(), tu fais
fflush(stdin);
, que tu devrais retirer, car en C standard fflush() n'est conçu pour travailler que sur des flux ouverts en écriture (le comportement de cette instruction est indéfini avec stdin en argument).

Dans la fonction Modification(), tu fais
if(fwrite(&Com,sizeof(COMMANDES),1,Fichier)<=0)
, ce qui n'a pas trop de sens car fwrite retourne un type size_t qui est un entier non signé.

Ta fonction Ajout() met le champ Valide à 1. Lorsque tu exécutes ta fonction Modification(), tu cherches des champs Valide égaux à 2, pour les mettre à 1. S'il n'y a pas de champs Valide avec une valeur de 2, c'est normal que rien ne soit modifié.

Si, en revanche, tu changes la fonction Modification pour changer les 1 en 2, le code suivant a l'air de fonctionner chez moi :

$ cat 35156345.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define Trace printf

typedef struct { 
	int	Valide;
	char	Nom[50];
} COMMANDES;

void Ajout(char *Com)
{
	Trace("AjoutCommande commence\n");
	FILE *Fichier;
	COMMANDES New;

	if ((Fichier = fopen("Commandes.dat","a")) == NULL) {
		Trace("Erreur de l'ouverture du Fichier (exit Personnel)\n");	
		exit(1);
	}

	strcpy(New.Nom,Com);
	New.Valide=1;
	fwrite(&New,sizeof(COMMANDES),1,Fichier);

	fclose(Fichier);

	Trace("Sortie Ajout\n");
}

void Modification(void)
{
	COMMANDES Com;
	FILE *Fichier;
	int Taille;
	int written;

	if((Fichier=fopen("Commandes.dat","r+"))!=NULL) {
		Taille=0;
		fread(&Com,sizeof(COMMANDES),1,Fichier);
		while (!feof(Fichier)) {
			Trace("Avant: %s\t%d\n",Com.Nom,Com.Valide);
			if(Com.Valide==1) {
				if(fseek(Fichier,(-sizeof(COMMANDES)),SEEK_CUR)!=0)
					Trace("Erreur\n");

				Com.Valide=2;
				Trace("Boucle modif\n");
				written = fwrite(&Com,sizeof(COMMANDES),1,Fichier);
				if ( (written == 0) || (written != sizeof(COMMANDES)) )
					Trace("Erreur ecriture\n");

				Trace("Après Modif: %s\t%d\n",Com.Nom,Com.Valide);
			}
			Taille++;
			fread(&Com,sizeof(COMMANDES),1,Fichier);
		}
		fclose(Fichier);
	} else {
		Fichier=fopen("Commandes.dat","w");
		fclose(Fichier);
	}
}

void AfficherCommande(void)
{
	COMMANDES Com;
	FILE *Fichier;

	Fichier=fopen("Commandes.dat","rb");
	if(Fichier!=NULL) {
		fread(&Com,sizeof(COMMANDES),1,Fichier);
		while (!feof(Fichier)) {
			Trace("%s\t%d\n",Com.Nom,Com.Valide);
			fread(&Com,sizeof(COMMANDES),1,Fichier);
		}
		fclose(Fichier);
	}
}

int main(void)
{
	Ajout("toto");
	AfficherCommande();
	getchar();
	Modification();
	AfficherCommande();

	return 0;
}


$ rm Commandes.dat ; gcc -Wall 35156345.c
$ ./a.out 
AjoutCommande commence
Sortie Ajout
toto 1

Avant: toto 1
Boucle modif
Erreur ecriture
Après Modif: toto 2
toto 2
$


J'ai un mis getchar() entre l'Ajout et la Modification, pour avoir le temps de faire un hexdump du fichier sur un autre terminal et vérifier son contenu brut entre les deux opérations.

Après Ajout() :
$ hexdump -C Commandes.dat
00000000  01 00 00 00 74 6f 74 6f  00 82 04 08 30 a9 72 b7  |....toto....0.r.|
00000010  00 00 00 00 bf 00 00 00  16 6f 5c b7 ff ff ff ff  |.........o\.....|
00000020  be 93 90 bf f8 db 53 b7  43 22 56 b7 00 00 00 00  |......S.C"V.....|
00000030  48 30 b4 2c 01 00 00 00                           |H0.,....|
00000038


après Modification() :
$ hexdump -C Commandes.dat
00000000  02 00 00 00 74 6f 74 6f  00 82 04 08 30 a9 72 b7  |....toto....0.r.|
00000010  00 00 00 00 bf 00 00 00  16 6f 5c b7 ff ff ff ff  |.........o\.....|
00000020  be 93 90 bf f8 db 53 b7  43 22 56 b7 00 00 00 00  |......S.C"V.....|
00000030  48 30 b4 2c 01 00 00 00                           |H0.,....|
00000038

On voit bien que seul le premier octet est modifié, qui correspond à l'octet de poids faible du int.

Dal
0