C : lire dans un fichier (!)

C : lire dans un fichier (!) - Programmation

Marsh Posté le 09-08-2001 à 11:28:26    

ben voila, j'ai fait un petit programme juste comme ca, un editeur hexa en gros
il ouvre un fichier en mode binaire, il lit un caractere, l'affiche, lit un caractere l'affiche etc ...
jusqu'a la fin
je test ...
ca a l'air de marcher
je sors un editeur hexa ...
ben non ca marche pas
s'il rencontre (fscanf()) un caractere qui vaut 255, pouf ca s'arrete
alors tiens, qu'est-ce donc que cela ?
je fouine un peu, et je comprend mieux : EOF vaut -1, soit 255 pour un unsigned char
 
donc ma boucle
    while((car=fscanf(...))!=EOF)
elle fouare
 
genant
je change pour fread, ben c'est pareil, malgre un while(!feof())
idem while(!feof()) et fscanf
 
j'ai enfin trouve une solution :
 
_getw() ou getw() selon
et avec feof ca marche
d'ailleurs dans l'aide il le disent de faire gaffe car EOF peut etre une valeur du fichier, et non sa fin
 
mais c'est pour des entiers
j'ai rien trouve qui marche pour des caracteres
alors quoi ? on peut pas lire un fichier qui contient 0xFF ?
comment fscanf et fread peuvent elles influencer sur la fin du fichier (feof renvoit true)


---------------
FAQ fclc++ - FAQ C++ - C++ FAQ Lite
Reply

Marsh Posté le 09-08-2001 à 11:28:26   

Reply

Marsh Posté le 09-08-2001 à 13:01:23    

Avec getc(), ca irait peut-être. :)  
C'est ce que j'utilisais dans mes débuts du C sous DOS (1995). La fonction retourne le caractère lu sous forme d'entier (donc de 0 à 255), ou EOF (-1) si fin de fichier. Il n'y a pas de risque de "confusion" caractériel. :D  
 
Syntax
 
#include <stdio.h>
int getc(FILE *stream);
wint_t getwc(FILE *stream);
 
Description
 
Gets character from stream.
getc returns the next character on the given input stream and increments the stream's file pointer to point to the next character.
 
Note: For Win32s or Win32 GUI applications, stdin must be redirected.
 
Return Value
 
On success, getc returns the character read, after converting it to an int without sign extension.  
On end-of-file or error, it returns EOF.

Reply

Marsh Posté le 09-08-2001 à 13:20:25    

On retrouve toujours les mêmes... :)
 
J'ai fait un essai de voici :
 
#include <stdio.h>
#include <stdlib.h>
 
int main()
{
   int  ret, count, total;
   unsigned char buffer;
   FILE *stream;
 
   if(!(stream = fopen( "file.bin", "rb" )))
   {
     perror("Erreur de flux" );
     ret = 1;
   }
   else
   {
     total = 0;
     while(!feof(stream))
     {
       count = fread( &buffer, 1, 1, stream);
       if( ferror(stream))
       {
         perror("Erreur de lecture" );
         break;
       }
       else
       {
         printf ("%02X ", buffer);
         total += count;
       }
     }
     printf( "Le fichier fait %d octet(s)\n", total );
     fclose( stream );
 
     ret = 0;
   }
 
   // valeur de retour de l'application
   return (ret);
}
 
---
 
J'utilise un fread, et feof, et ça marche très bien...
Ce programme lit (et affiche) octet par octet.
A la fin, il indique la taille lu qui doit etre celle du fichier.
Pas de problèmes avec 255.

Reply

Marsh Posté le 09-08-2001 à 13:29:14    

Sauf en septembre !  :sol:  :sol:
 
Il a une fonction eof() qui devrait remplacer if ( == EOF) (vu dans la doc tt à l'heure, jamais utilisée).
 
Syntax
 
#include <io.h>
int eof(int handle);
 
Description
 
Checks for end-of-file.
eof determines whether the file associated with handle has reached end-of-file.
 
Return Value
 
If the current position is end-of-file, eof returns the value 1; otherwise, it returns 0. A return value of -1 indicates an error; the global variable errno is set to
 
EBADF Bad file number

Reply

Marsh Posté le 09-08-2001 à 14:02:04    

moi aussi j'ai fais des essais
voici mon compte rendu

Code :
  1. FILE * fic;
  2. unsigned char octet;
  3. while(fscanf(fic,"%c",&octet)!=EOF)


 
ne marche pas
si fscanf rencontre l'octet 255 (-1), le programme quitte
de meme,

Code :
  1. while(fread(&octet,1,1,fic)!=EOF)


ne marche (meme chose)
 
j'ai pas teste

Code :
  1. while((octet=fgetc(fic))!=EOF)


mais ca va pas marcher a mon avis non plus
 
donc, bilan 1 : toujours utiliser feof(fic) dans la lecture d'un fichier la ca marche (ouf!)
 
mais c'est pas fini, y'a encore une surprise

Code :
  1. while(feof(fic)!=EOF)
  2. {
  3.     octet = fgetc(fic);
  4. }


ca, ca marche nickel

Code :
  1. while(feof(fic)!=EOF)
  2. {
  3.     freaf(&octet,1,1,fic);
  4. }


ca aussi c'est nickel
 

Code :
  1. while(feof(fic)!=EOF)
  2. {
  3.     fscanf(fic,"%c",&octet);
  4. }


là surprise !!!
si fscanf rencontre ce fameux octet 255, ben il est censuré, et remplacé par la valeur de l'octet précédement lu ! :ouch:
 
surprenant non ?
je crois que c'est bon à savoir ...
j'ai teste tout ca avec Borland C++ 4
 
donc regle 2 : se mefier de fscanf
 
TotOOntHeMooN >
donc ton code ne marche pas completement ! ;)

Code :
  1. while(!feof(stream))
  2. {
  3.     count = fread( &buffer, 1, 1, stream);
  4.     total += count
  5. }


 
count vaudra EOF si l'octet 255 est lu
en fait il vaudra -1
donc ton total peut se reveler errone a la fin
 
enfin c'est ce que mes test de tout a l'heure m'ont revele ...
j'ai fait ca vite alors petetre que je me goure
je vais aller encore checker ca
c'est quoi ton compilo (la library surtout) ?
 
et t'as bien utilise un editeur hexa pour vérifier ?


---------------
FAQ fclc++ - FAQ C++ - C++ FAQ Lite
Reply

Marsh Posté le 09-08-2001 à 14:11:54    

J'ai fait mon essai sous Visual C++ 6.0 (au travail), et comme tu peux le voir en haut du programme, j'ai utilisé <stdlib.h> et <stdio.h>. Ce programme devrait compiller sans problème sous tous les OS et avec n'iporte quel autre compilo. (gcc entre autre)
 
Count ne peut pas valoir EOF, puisque si la fin de fichier est rencontrée (feof), la lecture s'arette.
En cas d'erreur de lecture, tu devrais avoir le message associé qui s'affiche, et la effectivement, la valeur "total" sera erronée, autrement, elle vaudra bien la taille du fichier lu.
Je n'ai pas vérifié avec un éditeur Hexadécial, car le résultat s'avère correct (affichage) par rapport à mon fichier d'essai, qui comportait des 255 entre autre.

Reply

Marsh Posté le 09-08-2001 à 14:12:41    

En remplaçant unsigned char octet; par int octet; y a pas des fonctions qui "marcheraient" ?  
 :) J'ai pas le temps de regarder les arguments réclamés  :(  
 
Vu que l'int "monte plus haut" que le char, et que ce qu'on lit ce sont des chars (correspondance directe) le EOF est -1 de toute façon, mais on l'intercepte en int avant de faire char = int; donc espoir peut-être.  :D  
 
A me relire, c'est abscons ce que je dis.

Reply

Marsh Posté le 09-08-2001 à 14:18:03    

Au fait, fscanf n'est à utilisé qu'en cas de lecture d'un fichier texte. (0x20 à 0x7F)
Si tu veux lire en binaire et surtout dans un fichier binaire, qui est donc suceptible de retourner les valeurs entre 0x00 et 0xFF, il faut utiliser fread.
EOF est une macro à utiliser avec des fichiers ASCII.
Dans ton cas, il faut bien utiliser fonction feof().
 
Essai mon example ;)
Je ne dis pas qu'il est sans erreur, mais il ne m'en a pas donné l'impression.

Reply

Marsh Posté le 09-08-2001 à 14:20:54    

bon d'accord, count ne vaut pas EOF, mais en tous cas, apres mes tests, si fread rencontre l'octet 255, il renvoit -1
 
j'ai fait ca comme test :

Code :
  1. int count;
  2. while(!feof(fic))
  3. {
  4.     count = freaf(&octet,1,1,fic);
  5.     printf("%d ",count);
  6. }


 
et la j'ai des 1 partout sauf a chaque fois que y'a un 255 dans mon fichier (editeur hexa sous les yeux)
mais il me lit bien tous les octets du fichier
le truc, c'est qu'il renvoit -1 quand il lit 255
or -1, c'est EOF
moi je n'utilise que stdio.h
et dedans, y'a :
 
#define EOF -1
 
CARBON_14 > le probleme ne vient pas de octet
1 : fscanf attend un char donc si tu lui passe un int ca va faire mal
fread idem
getc je pense que ca ne va rien changer
 
count par contre doit etre un int
sinon on a un joli warning "conversion mail loss significant data"
et si tu met quand meme un char pour count, ben il vaudra -1 quand meme
enfin, j'ai pas trop pige ce que tu veux dire :D


---------------
FAQ fclc++ - FAQ C++ - C++ FAQ Lite
Reply

Marsh Posté le 09-08-2001 à 14:35:19    

Dans mon example, count me retourne 1 à chaque octet lu, même pour 255. (ce qui est logique)
Je pense que tu as un faut problème... En tout cas, il ne se trouve pas la...
Part de mon example, pour faire tes tests

Reply

Marsh Posté le 09-08-2001 à 14:35:19   

Reply

Marsh Posté le 09-08-2001 à 14:52:19    

Désolé si les arguments des fonctions ne veulent qu'un char. Ca résoudrait rien :( .
 
Pour getc(), on reçoit un INT d'office :) .
 
Je fabrique un fichier avec des char 255 de suite pour tester (pause boulot) si getc() retourne bien int 255 pour 255, et int -1 pour eof(fichier) sous DOS, bien sûr.

Reply

Marsh Posté le 09-08-2001 à 14:59:44    

j'ai refait mes tests et me suis appercu que je me suis gouré dans mon "compte rendu" :O
 
alors voila, tant qu'a faire, j'ai teste mes source qouq BC++ et sous MS VC++
 
en fait c'est pas fread qui pose probleme mais fscanf ...
 
j'ai en gros fait ca :
ton code :

Code :
  1. int total=0, count=0;
  2. while(!feof(fic)
  3. {
  4.     total += count;
  5.     count = freaf(&octet,1,1,fic);
  6.     printf("%d ",count);
  7. }
  8. printf("\n%d",total);


et aussi

Code :
  1. while(!feof(fic)
  2. {
  3.     total += count;
  4.     count = fscanf(fic,"%c",&octet);
  5.     printf("%d ",count);
  6. }
  7. printf("\n%d",total);


 
resultat :
sous les 2 environnement, fread renvoit 1 tout le temps, meme quand y'a 255, sauf quand il atteind la fin du fichier (d'ou le total += count au debut de la boucle)
la taille du fichier renvoyee est correcte
 
par contre, pour ce cher scanf
sous MS VC++, pas de probleme, ca fait comme pour fread
mais pour le Borland, ben ca merde bien comme il faut
c'est lui qui me renvoit -1 a chaque foit qu'il croise un 255 :fou:
donc la taille du fichier est invalide
 
donc mea culpa, mea maxima culpa
ton code est parfait :jap:
 
donc moi scanf celui la il peut aller se faire voire
 
et donc un code tel que :

Code :
  1. while((count = freaf(&octet,1,1,fic))==1)


 
fonctionne parfaitement et vous pouvez oublier mes deux regles a la con
sauf petetre la 2°
 
fread renvoit 0 (logique) quand il rencontre une fin de fichier
fscanf, lui, renvoit -1 (EOF)
 
voila qui est eclairci
merci de votre aide ;)


---------------
FAQ fclc++ - FAQ C++ - C++ FAQ Lite
Reply

Marsh Posté le 09-08-2001 à 15:01:03    

Essai getc(255)... Bof, le caractère est avalé, envoyé aux oubliettes, on continue normalement jusqu'à la fin de fichier, et tous les FFH que j'avais mis sont oubliés, perdus, jetés.
 
Donc, c'est pas bon cette fonction..
Désolé.  :(

Reply

Marsh Posté le 09-08-2001 à 15:14:15    

Le sprintf de micro$oft est donc mal codé, car il ne devrait logiquement pas fonctionner avec un fichier binaire !
 
Bonne chance pour la suite de ton programme.
 
Si tu utilises que des fread, fwrite, feof, fopen en précisant le "b", pour binaire, etc... alors tu ne rencontrera pas de problèmes. :)

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed