Partage
  • Partager sur Facebook
  • Partager sur Twitter

Panique dans la manipulation des fichiers

Sujet résolu
    28 novembre 2010 à 10:55:51

    Bonjour à tous,
    Voilà un moment que je n'étais plus revenu pour vous soumettre un problème. Cette fois-ci, il s'agit de manipulation de fichiers.

    Je ne comprends pas du tout pourquoi le petit programme bidon ci-dessous ne fonctionne pas :

    #include<windows.h>
    #include<stdio.h>
    
    static int read (FILE* fp) {
    if (!fp) { printf("FP is null !\r\n"); return; }
    int x=0;
    int re = fread(&x, 1, sizeof(x), fp);
    if (re!=sizeof(x) || ferror(fp)) printf("Read error\r\n");
    return x;
    }
    
    static void write (FILE* fp, int n) {
    if (!fp) { printf("FP is null !\r\n"); return; }
    int re = fwrite(&n, 1, sizeof(n), fp);
    if (re!=sizeof(n) || ferror(fp)) printf("Write error\r\n");
    }
    
    int main (int argc, char** argv) {
    const char fn[] = "test3.dat";
    FILE* fp = NULL;
    int a=0, b=0, c=0, x=0;
    
    fp = fopen(fn, "wb");
    write(fp, 1);
    write(fp, 2);
    write(fp, 3);
    fflush(fp);
    fclose(fp);
    Sleep(1000);
    
    fp = fopen(fn, "r+b");
    x = read(fp);
    printf("x=%d\r\n", x); // 1
    write(fp, x+10);
    fflush(fp);
    fclose(fp);
    Sleep(1000);
    
    fp = fopen(fn, "rb");
    a = read(fp);
    b = read(fp);
    c = read(fp);
    printf("a=%d, b=%d, c=%d\r\n", a, b, c); // 1, 11, 3
    fclose(fp);
    Sleep(1000);
    
    fp = fopen(fn, "r+b");
    write(fp, 100);
    x = read(fp);
    printf("x=%d\r\n", x); // 11
    write(fp, x+10);
    fflush(fp);
    fclose(fp);
    Sleep(1000);
    
    fp = fopen(fn, "rb");
    a = read(fp);  b = read(fp); c = read(fp);
    printf("a=%d, b=%d, c=%d\r\n", a, b, c); // 100, 11, 21
    fclose(fp);
    Sleep(1000);
    
    remove(fn);
    
    return 0;
    }
    


    J'obtiens la sortie suivante :
    x=1
    a=1, b=2, c=3
    x=4086080
    a=100, b=4086080, c=4086090


    Alors que je m'attends à :
    x=1
    a=1, b=11, c=3
    x=11
    a=100, b=11, c=21


    Autrement dit, le remplacement du deuxième int du fichier (offsets 4 à 8) n'a pas du tout lieu, et la relecture suivante me donne n'importe quoi (quoi que la dernière écriture du troisième int (offsets 8 à 12) a apparament marché malgré tout)

    Dans mon vrai programme, il est important que je puisse à la fois lire et écrire dans mon fichier, d'où le mode r+. IL semblerait que ce mode soit passablement buggé...

    OS : windows XP 32 bits
    Compilateur : MinGW 3.4.5

    J'ai pas essayé sous linux, mais je suis sûr que le pire, c'est que ça marche (hormis les Sleep bien sûr, mais de toute façon ils sont essentiellement là pour faire beau)

    Est-ce que quelqu'un a une idée ?
    Merci.
    • Partager sur Facebook
    • Partager sur Twitter
      28 novembre 2010 à 11:05:25

      Sous FreeBSD:

      x=1
      a=1, b=2, c=3
      x=2
      a=100, b=2, c=3
      


      Thegolum
      • Partager sur Facebook
      • Partager sur Twitter
        28 novembre 2010 à 12:20:19

        Tes fread et fwrite ne sont pas bons :

        le 2e et 3e argument, c'est d'abord la taille, puis le nombre.


        Donc :
        int re = fread(&x, sizeof(x),1, fp);

        Essaie. (et pareil pour fwrite)
        • Partager sur Facebook
        • Partager sur Twitter

        Recueil de code C et C++  http://fvirtman.free.fr/recueil/index.html

          28 novembre 2010 à 13:33:59

          Citation


          Tes fread et fwrite ne sont pas bons :
          le 2e et 3e argument, c'est d'abord la taille, puis le nombre.

          Donc :
          int re = fread(&x, sizeof(x),1, fp);

          Essaie. (et pareil pour fwrite)


          Ce n'est pas censé avoir une incidence n'est-ce pas ? fread et fwrite n'ont pas à savoir si j'écris 4 chars ou 1 int, la seule chose qui leur importe c'est que je vais écrire 4 octets. Ce sont biens des buffers sous forme de void*, le type exact n'importe donc pas.
          L'avantage de faire ce que j'ai fait, c'est qu'en retour j'obtiens le nombre d'octets lus ou écrits... en inversant les paramètres, j'obtiens toujours 1, ce qui n'a pas une grande signification (disons que connaître le nombre exact d'octets écrits peut avoir une utilité au-delà de savoir si succès/échec)

          J'ai tout de même essayé, mais comme on pouvait s'y attendre, ça ne change strictement rien. Ca a juste changé la valeur autour de 4000000 qui semblait de toute façon tomber de nulle part. A noter que quand j'exécute le programme avec gdb, cette valeur apparament aléatoire change aussi.
          • Partager sur Facebook
          • Partager sur Twitter
            28 novembre 2010 à 14:03:46

            Pour l'incidence que ça peut avoir, est ce que ça ne peut pas tomber sous le coup de l'endianness.

            Je pense que non, mais j'ai toujours un doute.

            Bon, tu dis que tu as essayé et que ça ne change pas.

            Pour ma part, je te dirais que je ne fais jamais de "r+", soit j'écris, soit je lis. Je n'aime pas mélanger. Est ce que le soucis pourrait venir de la ? Est ce que "w+" fait la meme chose ?
            • Partager sur Facebook
            • Partager sur Twitter

            Recueil de code C et C++  http://fvirtman.free.fr/recueil/index.html

              28 novembre 2010 à 14:09:34

              J'hésitais à poser la question, mais comme Fvirtman, un fichier ouvert en lecture, écriture ne m'inspire pas confiance...
              Ca pose pas mal de problèmes.

              Tu peux préciser pourquoi, tu dois faire ça?
              • Partager sur Facebook
              • Partager sur Twitter
              Zeste de Savoir, le site qui en a dans le citron !
                28 novembre 2010 à 15:36:16

                Citation

                Pour l'incidence que ça peut avoir, est ce que ça ne peut pas tomber sous le coup de l'endianness. Je pense que non, mais j'ai toujours un doute.


                JE ne vois pas ce que l'endianess vient faire ici. J'écris des int et je les relis juste après, je suis toujours sur la même machine donc logiquement, non. En plus cette valeur bizarre n'a strictement rien à voir avec le nombre 11 et ce n'est pas la même dans gdb ou en dehors. Rien ne va dans ce sens...

                Citation

                Je n'aime pas mélanger. Est ce que le soucis pourrait venir de la
                ? Est ce que "w+" fait la meme chose ?


                LE problème de w+, c'est qu'il écrase quand même le contenu à l'ouverture. En fait ma stratégie à la base c'est que j'ouvre le fichier en R+, et si ça foire je l'ouvre en W+ (parce que r+ échoue si le fichier n'existe pas déjà).
                JE vais malgré tout faire un autre test, juste pour voir.

                Citation

                Tu peux préciser pourquoi, tu dois faire ça?


                JE suis en train de m'amuser à écrire un éditeur de fichier binaires en ligne de commande, si possible multiplateforme. Je sais, c'est ni très original ni très utile.

                JE pensais que c'était mieux de faire ainsi plutôt que d'agir sur des buffer comme on le fait habituellement, au cas où on souhaiterait éditer de gros fichiers. Mais bon, si ça ne marche pas, j'en reviendrai à cette solution qui est au moins sûre de marcher.
                • Partager sur Facebook
                • Partager sur Twitter
                  28 novembre 2010 à 18:20:43

                  J'avoue que je sèche. :-°

                  Si on remplace le read par un ftell pour venir se placer au bon endroit, ça fonctionne.
                  Par contre l'enchainement fread, fwrite, dans un fichier r+, ne semble pas fonctionner sous Windows.


                  o_O
                  • Partager sur Facebook
                  • Partager sur Twitter
                  Zeste de Savoir, le site qui en a dans le citron !
                    28 novembre 2010 à 18:41:33

                    Pour les modes d'ouverture bidirectionnels (r+, a+, w+...) une lecture suivie d'une écriture représente un comportement indéfini (selon la norme).

                    Il faut toujours flusher le fichier entre deux opérations différentes (écriture suivie de lecture ou lecture suivie d'écriture. Sauf une lecture qui a résulté à un EOF). Pour flusher le fichier la norme préscrit l'une des fonctions : fflush, fseek ou rewind.

                    Donc revoies ton code.

                    Et au lieu de fermer le fichier pour le ré-ouvrir derrière, il existe freopen. Et 1 seconde n'est peut être pas suffisante, bref c'est code qui peut avoir un comportement hasardeux selon si l'OS a eu le temps de fermer le flux avant l'écoulement d'une seconde ou pas.
                    • Partager sur Facebook
                    • Partager sur Twitter
                      28 novembre 2010 à 18:44:34

                      @Uknow:
                      J'ai essayé de "fflush" entre les fread et fwrite, avec le code de Quentin C 2, sans résultat...

                      edit:
                      d'ailleurs, ça provoque une erreur au write suivant le fflush. o_O
                      En revanche ça fonctionne avec fread suivi, d'un fseek, et d'un fwrite.

                      Pourtant, si je fais un ftell après le read, je trouve bien la taille d'un entier, pourtant le fwrite suivant ne fonctionne pas.
                      • Partager sur Facebook
                      • Partager sur Twitter
                      Zeste de Savoir, le site qui en a dans le citron !
                        28 novembre 2010 à 19:15:28

                        Citation : GurneyH

                        edit:
                        d'ailleurs, ça provoque une erreur au write suivant le fflush. o_O
                        En revanche ça fonctionne avec fread suivi, d'un fseek, et d'un fwrite.

                        Pourtant, si je fais un ftell après le read, je trouve bien la taille d'un entier, pourtant le fwrite suivant ne fonctionne pas.



                        Oui pour moi aussi, il se peut qu'on ait trop demandé à l'OS ?!
                        fflush pousse l'OS à mettre le fichier à jour dans le DD, sans même parler des buffers ouverts en RAM, et généralement ce genre de requêtes ne sont pas prioritaires pour l'OS donc il prend son temps pour le faire.

                        Je me demande dans quels cas ce genre de pratiques seraient justifiées ? (je pense dans aucun cas).
                        • Partager sur Facebook
                        • Partager sur Twitter
                          28 novembre 2010 à 19:50:15

                          Citation

                          Pour les modes d'ouverture bidirectionnels (r+, a+, w+...) une lecture suivie d'une écriture représente un comportement indéfini (selon la norme).

                          Il faut toujours flusher le fichier entre deux opérations différentes (écriture suivie de lecture ou lecture suivie d'écriture. Sauf une lecture qui a
                          résulté à un EOF). Pour flusher le fichier la norme préscrit l'une des fonctions : fflush, fseek ou rewind.


                          Les flush après chaque changement de direction ne règlent pas le problème.
                          * Si on est en mode lecture et qu'on fait un flush, ça fait planter les écritures suivantes (dans mon code ça affiche write error). Dans un certain sens c'est logique, on n'a pas à flusher un flux de lecture, c'est un comportement indéfini.
                          * Si on ne fait pas de flush après les read et avant les write, alors les write ne fonctionnent pas, bien qu'il n'y ait aucune erreur.

                          Flush mène donc à une impasse. Si par contre je remplace chaque flush par fseek(fp, 0, SEEK_CUR), ça marche... mais je ne comprends absolument pas pourquoi. En principe, c'est une action inutile, puisque ça équivaut à sauter sur place.

                          Citation

                          Et au lieu de fermer le fichier pour le ré-ouvrir derrière, il existe freopen. Et 1 seconde n'est peut être pas suffisante, bref c'est code qui peut avoir
                          un comportement hasardeux selon si l'OS a eu le temps de fermer le flux avant l'écoulement d'une seconde ou pas.


                          Même si on met des sleep plus longs, ça ne change rien, j'ai aussi essayé.
                          En ce qui concerne freopen, c'est voulu que je ne l'utilise pas: dans mon cas réel avec mon vrai fichier, c'est justement entre deux lancements du programme, et donc forcément en plusieurs ouvertures successives, que je constate des données erronnées.

                          Je viens de découvrir un autre fait intéressant avec mon exemple : si je ne supprime pas le fichier à la fin, en l'ouvrant dans un éditeur hexadécimal, je vois bien les octets 4 à 8 qui contiennent n'importe quoi, même si je rouvre le fichier plusieurs minutes plus tard.
                          • Partager sur Facebook
                          • Partager sur Twitter
                            28 novembre 2010 à 20:02:24

                            Citation : C99

                            When a file is opened with update mode ('+' as the second or third character in the
                            above list of mode argument values), both input and output may be performed on the
                            associated stream. However, output shall not be directly followed by input without an
                            intervening call to the fflush function or to a file positioning function (fseek,
                            fsetpos, or rewind), and input shall not be directly followed by output without an
                            intervening call to a file positioning function, unless the input operation encounters endof-
                            file.
                            Opening (or creating) a text file with update mode may instead open (or create) a
                            binary stream in some implementations.



                            Pour ce que tu as trouvé dans le fichier ne serait-ce pas EOF ?
                            • Partager sur Facebook
                            • Partager sur Twitter
                              28 novembre 2010 à 20:08:22

                              Citation

                              Pour ce que tu as trouvé dans le fichier ne serait-ce pas EOF ?


                              Tu veux dire quoi par là ? la valeur EOF dans le fichier lui-même ? Qu'est-ce qu'elle viendrait y faire ?
                              • Partager sur Facebook
                              • Partager sur Twitter
                                28 novembre 2010 à 20:26:58

                                @Quentin C 2:

                                Je pense que tu pourrais poser le problème sur comp lang c.fr.

                                En proposant un code minimal, qui reproduit le problème(clair et bien indenté, aussi ;) ) , tu devrais avoir des réponses intéressantes!

                                Je n'ai jamais utilisé un fichier en lecture/écriture, et finalement, je ne regrette pas.

                                Mais je serais curieux, d'avoir une explication. :-°
                                • Partager sur Facebook
                                • Partager sur Twitter
                                Zeste de Savoir, le site qui en a dans le citron !
                                  28 novembre 2010 à 20:52:02

                                  @GurneyH: tu es au moins le troisième qui m'envoie sur usenet, malheureusement je n'ai aucune idée de comment ça fonctionne au juste. Je ne crois pas que j'aie de programme pour lire ça, et j'ai pas l'impression qu'on peut s'inscrire et poster directement sur le web comme dans un forum normal. Dommmage, ça a l'air d'être de sacrées pointures là-bas...
                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    28 novembre 2010 à 22:26:20

                                    Et bien, il faut s'inscrire. Point...

                                    Tu sais quoi, je pense que je vais poser la question. ;)

                                    Je n'aime vraiment pas avoir des interrogations sur des points de ce genre.

                                    Je vais dans la semaine, te proposer(par MP), un code qui reproduit le problème.

                                    Avec ton accord, je poserai la question sur comp lang c...

                                    et, oui, il y a des pointures, et elles sont sympa...
                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                    Zeste de Savoir, le site qui en a dans le citron !
                                      29 novembre 2010 à 5:39:27

                                      Citation

                                      Je vais dans la semaine, te proposer(par MP), un code qui reproduit le problème.


                                      Celui que j'ai actuellement ne va pas ?

                                      Citation

                                      Avec ton accord, je poserai la question sur comp lang c...


                                      Tu en as l'autorisation.
                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                        29 novembre 2010 à 10:21:39

                                        Citation : Quentin C 2


                                        Celui que j'ai actuellement ne va pas ?


                                        Disons qu'entre la présentation, et l'inversion des paramètres size et nmemb de fread et fwrite(même si c'est correct ici), ça risquait de mal passer.

                                        Question posée ici.
                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                        Zeste de Savoir, le site qui en a dans le citron !
                                          29 novembre 2010 à 10:53:19

                                          Salut,

                                          Je me trompe peut-être mais avez-vous essayer en ouvrant trois fois le fichier en mode binaire ? Ce problème m'a fait penser à ce passage du livre "Méthodologie de la programmation en C" :

                                          Citation : Méthodologie de la programmation en C p 267


                                          De manière générale il existe deux types de flots :

                                          - Les flots texte dont le contenu est découpé en lignes séparées par le catactère '\n'. Le contenu du flot peut subir des modifications selon les conventions de représentation de texte de l'environnement, comme par exemple la suppression des espaces précédant un caractère '\n'.

                                          - Les flots binaires qui permettent de transférer sans altération le codage interne des données.

                                          Sur certains systèmes, les flots texte peuvent être restreints de sorte qu'ils peuvent seulement transmettre des caractères affichables et certains caractères de contrôle. Par contre, les flots binaires ne comportent aucune restriction.

                                          Cette distinction entre flots texte et flots binaires et imposée par la compatibilité avec des systèmes dans lesquels les applications orientées textes utilisent un format de fichier spécifique. Elle n'a pas de sens sous un système UNIX ou un système compatible POSIX, tous les fichiers étant dans ce cas gérés de façon homogène.

                                          • Partager sur Facebook
                                          • Partager sur Twitter
                                            29 novembre 2010 à 11:04:24

                                            Oui, c'est ce qu'on faisait au début.

                                            Je me suis planté sur le code planté sur comp lang c.

                                            Mais Quentin C 2 précisait bien le mode d'ouverture binaire.

                                            edit: corrigé sur comp lang c.
                                            d'ailleurs le code
                                            #include <stdio.h>
                                            #include <stdlib.h>
                                            
                                            FILE *xfopen(char const *path, char const *mode)
                                            {
                                                FILE *fp = fopen(path, mode);
                                                if(fp == NULL)
                                                {
                                                    perror("xfopen ");
                                                    exit(EXIT_FAILURE);
                                                }
                                                return fp;
                                            
                                            }
                                            
                                            int read_int(FILE *fp)
                                            {
                                                int ret;
                                                if(fread(&ret, sizeof(int), 1, fp) < 1)
                                                {
                                                    fprintf(stderr, "Error: read_int");
                                                    exit(EXIT_FAILURE);
                                                }
                                                return ret;
                                            
                                            }
                                            
                                            void write_int(FILE *fp, int n)
                                            {
                                                if(fwrite(&n, sizeof(int), 1, fp) < 1)
                                                {
                                                    fprintf(stderr, "Error :  write_int");
                                                    exit(EXIT_FAILURE);
                                                }
                                            
                                            }
                                            
                                            int main(void)
                                            {
                                                int i, n;
                                                char const *filename = "test.txt";
                                                FILE *fp = NULL;
                                            
                                                /* write */
                                                fp = xfopen(filename, "wb");
                                                for(i = 0; i < 3; i++)
                                                    write_int(fp, i + 1);
                                                fclose(fp); /* 1 2 3 */
                                            
                                                /* read / write */
                                                fp = xfopen(filename, "rb+");
                                                n = read_int(fp);
                                                printf("n = %d\n", n);
                                                write_int(fp, n + 10);
                                                fclose(fp); /* 1 11 3 */
                                            
                                                /* read */
                                                fp = xfopen(filename, "rb");
                                                for(i = 0; i < 3; i++)
                                                    printf("%d\n", read_int(fp));
                                                fclose(fp);
                                            
                                                return 0;
                                            
                                            }
                                            
                                            • Partager sur Facebook
                                            • Partager sur Twitter
                                            Zeste de Savoir, le site qui en a dans le citron !
                                              29 novembre 2010 à 13:48:51

                                              Citation

                                              Mais Quentin C 2 précisait bien le mode d'ouverture binaire.


                                              Oui, c'est très important.

                                              Sous linux, ça ne change pas grand chose.

                                              Par contre sous windows, le mode texte fait que chaque \n seul est remplacé automatiquement par \r\n. Écrire des données binaires a donc toutes les chances de foirer de façon complètement inattendue si on ne le précise pas explicitement.

                                              Merci GurneyH pour avoir posé la question là-bas.
                                              • Partager sur Facebook
                                              • Partager sur Twitter
                                                29 novembre 2010 à 17:30:07

                                                La réponse m'a été donnée.
                                                Il semble que ce soit un bug dans l'implémentation de stdio.h par Microsoft.
                                                (au moins dans le sens lecture, suivi d'une écriture, comme dans le code que j'ai présenté).

                                                La solution est de placer
                                                fseek(fp, 0, SEEK_CUR);
                                                

                                                entre 2 opérations avec le mode "rb+"

                                                J'ai testé avec ton code du premier post, ça fonctionne. :)

                                                Voir la réponse sur fr.comp.lang.c, pour les détails.
                                                • Partager sur Facebook
                                                • Partager sur Twitter
                                                Zeste de Savoir, le site qui en a dans le citron !
                                                  29 novembre 2010 à 20:28:46

                                                  Citation : GurneyH


                                                  Mais Quentin C 2 précisait bien le mode d'ouverture binaire.



                                                  Au temps pour moi :-°

                                                  Merci pour la question posée sur fr.comp.lang.c GurneyH, mais j'ai une question suite à cette réponse: uknow a posté ce passage de la Norme C99 :

                                                  Citation : Norme C99 7.19.5.3 p 218


                                                  When a file is opened with update mode ('+' as the second or third character in the
                                                  above list of mode argument values), both input and output may be performed on the
                                                  associated stream. However, output shall not be directly followed by input without an
                                                  intervening call to the fflush function or to a file positioning function (fseek,
                                                  fsetpos, or rewind), and input shall not be directly followed by output without an
                                                  intervening call to a file positioning function
                                                  , unless the input operation encounters end-
                                                  of-file. Opening (or creating) a text file with update mode may instead open (or create) a
                                                  binary stream in some implementations.



                                                  Or si je lis bien, celle-ci dit explicitement que si l'on ouvre un fichier en "update mode"(avec un "+" ), les opérations d'écriture ne doivent pas suivre les opérations de lecture sans un appel à ftell fsetpos, fseek ou rewind(sauf si la lecture atteint la fin du fichier). Si c'est bien juste, Windows respecte bel et bien la Norme. Me trompai-je ?
                                                  • Partager sur Facebook
                                                  • Partager sur Twitter
                                                    29 novembre 2010 à 21:00:08

                                                    Je pense que c'est conforme à la norme, l'erreur que nous avons faite c'est d'avoir utilisé fflush sur un flux d'"update" dont la dernière opération était une lecture, ce qui est énoncé parmi les cas indéfinis dans l'annexe J2 - Undefined behavior. Et la réponse apportée par GurneyH ne fait que confirmer le passage 7.19.5.3 -(6.
                                                    • Partager sur Facebook
                                                    • Partager sur Twitter
                                                      29 novembre 2010 à 21:43:10

                                                      Merci Uknow, GurneyH et taurre. La solution est donc de faire fseek(fp, 0, SEEK_SET) à chaque fois qu'on change de mode, pour être sûr de ne rien laisser passer.

                                                      Entre temps j'ai attentivement fouillé les arcanes de stdio.h et je suis tombé sur la fonction setbuf. Elle a l'air d'être standard et résoud apparament également le problème initial. En ajoutant setbuf(fp,NULL) juste après l'ouverture du fichier, ça désactive le buffering.
                                                      Qu'en pensez-vous ? S'agit-il vraiment d'une fonction standard et non pas propre à la MSVCRT (comment savoir) ? Est-ce que cette solution marche aussi ailleurs que sous windows ?
                                                      • Partager sur Facebook
                                                      • Partager sur Twitter
                                                        29 novembre 2010 à 21:59:42

                                                        Citation : QuentinC 2

                                                        Qu'en pensez-vous ? S'agit-il vraiment d'une fonction standard et non pas propre à la MSVCRT (comment savoir) ? Est-ce que cette solution marche aussi ailleurs que sous windows ?



                                                        C'est une fonction standard (d'après la C99), donc tu as la garantie qu'elle agira de la même façon énoncée dans sa page man quelque soit l'implémentation et l'environnement.

                                                        Pour ce qui est de son rapport avec le problème initial, j'ai tendance à dire que si la norme explicite qu'il faut utiliser une fonction de positionnement dans un cas identique à celui qu'on a là sans citer d'exceptions, alors il n'y a pas d'autres façons sûres de faire.
                                                        • Partager sur Facebook
                                                        • Partager sur Twitter
                                                          30 novembre 2010 à 4:10:12

                                                          Citation : Taurre


                                                          Or si je lis bien, celle-ci dit explicitement que si l'on ouvre un fichier en "update mode"(avec un "+" ), les opérations d'écriture ne doivent pas suivre les opérations de lecture sans un appel à ftell fsetpos, fseek ou rewind(sauf si la lecture atteint la fin du fichier). Si c'est bien juste, Windows respecte bel et bien la Norme. Me trompai-je ?


                                                          Non, tu ne te trompes pas, c'est écrit noir sur blanc. :D
                                                          La personne qui m'a répondu sur comp lang.c avait un doute sur ce point.

                                                          Je pense tout de même que le mode lecture/écriture, est très peu utilisé.
                                                          D'ailleurs, il serait intéressant de trouver des sources "sérieux", qui l'utilise.
                                                          • Partager sur Facebook
                                                          • Partager sur Twitter
                                                          Zeste de Savoir, le site qui en a dans le citron !
                                                            30 novembre 2010 à 15:58:21

                                                            Citation : ukonw


                                                            Je pense que c'est conforme à la norme, l'erreur que nous avons faite c'est d'avoir utilisé fflush sur un flux d'"update" dont la dernière opération était une lecture, ce qui est énoncé parmi les cas indéfinis dans l'annexe J2 - Undefined behavior. Et la réponse apportée par GurneyH ne fait que confirmer le passage 7.19.5.3 -(6.



                                                            Citation : GurneyH


                                                            Non, tu ne te trompes pas, c'est écrit noir sur blanc. :D



                                                            Merci pour la confirmation ^^

                                                            Citation : QuentinC 2


                                                            Entre temps j'ai attentivement fouillé les arcanes de stdio.h et je suis tombé sur la fonction setbuf. Elle a l'air d'être standard et résoud apparament également le problème initial. En ajoutant setbuf(fp,NULL) juste après l'ouverture du fichier, ça désactive le buffering.
                                                            Qu'en pensez-vous ? S'agit-il vraiment d'une fonction standard et non pas propre à la MSVCRT (comment savoir) ? Est-ce que cette solution marche aussi ailleurs que sous windows ?



                                                            Les fonctions setbuf et setvbuf sont bel et bien des fonctions standard(depuis le C89). Quant à leur impact sur le problème j'ai, comme uknow, un doute. Le fait que l'on doive faire appel à fseek, fsetpos ou rewind entre une lecture/écriture ne me semble pas lié au tampon puisque ces fonctions n'ont aucune influence dessus. De plus, le fait de ne pas utilisé de tampon risque de ralentir les opérations de lecture/écriture étant donné que tu va multiplier les appels système.

                                                            EDIT :

                                                            Citation : QuentinC 2


                                                            (comment savoir)



                                                            Pour savoir si une fonction est standard ou pas il te suffit de regarder dans la Norme C99.
                                                            Concernant la Norme C89 je ne connais pas de liens gratuit pour en disposer. En ce qui me concerne je me réfère au K&R. Sinon, il y a aussi le sujet de rz0 listant les fonctions standard du C89. ;)
                                                            • Partager sur Facebook
                                                            • Partager sur Twitter
                                                              30 novembre 2010 à 17:56:25

                                                              Citation

                                                              le fait de ne pas utilisé de tampon risque de ralentir les opérations de lecture/écriture étant donné que tu va multiplier les
                                                              appels système.


                                                              Ca c'est certain, c'est même pas un risque, à mon avis c'est 100% exact.

                                                              Mais de toute façon le buffer est obligé de se vider quand on fait fseek, donc ça ne doit en fait pas changer grand chose au niveau des performances, qui seront de toute façon relativement catastrophiques par rapport à une lecture ou une écriture classique.

                                                              Merci pour toutes vos réponses, vos points de vue ont tous étés éclairants. JE pense qu'on a fait le tour du problème cette fois-ci, je considère donc ce sujet comme résolu.

                                                              Citation

                                                              Je pense tout de même que le mode lecture/écriture, est très peu utilisé.
                                                              D'ailleurs, il serait intéressant de trouver des sources "sérieux", qui l'utilise.


                                                              J'avoue que je serais aussi curieux de savoir. Si quelqu'un sait des choses là-dessus, qu'il n'hésite pas à poster même si ce sujet est résolu.

                                                              P.S. Je garde une copie de la norme, ça pourra toujours servir, on ne sait jamais.
                                                              • Partager sur Facebook
                                                              • Partager sur Twitter

                                                              Panique dans la manipulation des fichiers

                                                              × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                                              × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                                              • Editeur
                                                              • Markdown