Partage
  • Partager sur Facebook
  • Partager sur Twitter

Probleme décallage d'un octet fwrite/fread

Sujet résolu
    27 novembre 2020 à 14:14:31

    Bonjour.

    Débutant en C, je fais appel à la communauté car je fais face à un phénomène que j'ai du mal à m'expliquer dans l'utilisation des fonctions fwrite et fread et que je vais tenter d'exposer au mieux.

    Dans l'exemple suivant on enregistre séquentiellement dans un fichier des entiers entrés au clavier, en affichant leur position en mémoire. Je précise que sur ma machine un entier vaut 4 octets.

    int main()
    {
        char nomfich[21];
        int n;
        FILE * sortie;
    
        printf("nom du fichier a creer : ");
        scanf("%20s", nomfich);
        sortie = fopen (nomfich, "w");
    
        do {printf ("donnez un entier qui sera stocke a l'adresse %d : ",ftell(sortie));
            scanf ("%d", &n);
            if (n) fwrite (&n, sizeof(int), 1, sortie);
            }
        while (n);
    
        fclose(sortie);
    }

     Voici un exemple d’exécution avec un fichier nommé "test : On s'aperçoit que chaque fois que la valeur entrée est "10", le pointeur de positionnement de l'entier suivant se décale non pas de 4 mais de 5 octets.

    Une lecture séquentielle des valeurs entrées dans ce fichier par l'intermédiaire du programme suivant utilisant fread fonctionne

     int main()
    {
      char nomfich[21];
        int n;
        FILE * entree;
    
        printf("nom du fichier a lister : ");
        scanf("%20s", nomfich);
        entree=fopen(nomfich,"r");
        printf("adresse depart : %d, ",ftell(entree));
    
        while (fread (&n, sizeof(int), 1, entree), ! feof(entree))
            {   printf("\nvaleur=%d, ",n);
                printf("adresse suivante : %d",ftell(entree));   }
    
        fclose(entree);
    }


    et le décalage est bien pris en compte.

    Toutefois une lecture séquentielle avec la routine précédente d'un fichier rempli par accès direct par une boucle type

    while (printf("\nrang de l'entier : "), scanf("%ld", &num),num)
            {   printf("valeur de l'entier : ");
                scanf ("%d", &n);
                fseek (sortie, sizeof(int)*(num-1), SEEK_SET);
                fwrite(&n, sizeof(int), 1, sortie);}

    rend un résultat erronée et décalée d'un octet sitôt que l'on a rencontré une valeur égale à 10.

    Il en va de même avec la lecture directe d'un entier particulier dans un fichier rempli séquentiellement, par exemple via

    while (printf(" numero de l'entier recherche : "),
               scanf ("%ld", &num), num)
            { fseek (entree, sizeof(int)*(num-1), SEEK_SET);
                fread(&n, sizeof(int),1, entree);
                printf(" valeur : %d \n", n);}
    


    Je précise que j'utilise Code::Blocks 20.03, avec GNU GCC Compiler.


    Si quelqu'un connait l'explication à ce phénomène cela me permettrait de bien avancer dans la compréhension de l'utilisation des fichiers.

    Merci.

    -
    Edité par julecnd 27 novembre 2020 à 14:27:44

    • Partager sur Facebook
    • Partager sur Twitter
      27 novembre 2020 à 14:27:40

      Salut,

      Tu ouvres ton fichier avec "r" et "w" -> mode texte.

      Donc suivant la norme Windows des modes textes, le code de retour à la ligne fait 2 octets : 0x0D0A   (10 = 0x0A)

      Donc en mode texte est automatiquement ajouté un 2e caractère quand tu écris un caractère de retour de ligne.

      Si tu veux ne pas avoir ce soucis, passe en mode binaire dans fopen : "rb"  "wb"

      • Partager sur Facebook
      • Partager sur Twitter

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

        30 novembre 2020 à 12:02:23

        Salut.

        Merci pour ta réponse.

        Effectivement, cela fonctionne en passant en mode binaire. Merci beaucoup.

        Néanmoins, en relisant mon fichier octet par octet, je m'aperçois que le caractère ajouté n'est pas 0x0D comme on pouvait s'y attendre mais un second 0x0A.  Je n'ai donc pas la série CR LF 0x0D0A mais 0x0A0A. La valeur 10 entrée comme donnée de fichier parait être prise en compte en tant que telle et semble engendrer un retour à la ligne codé uniquement avec 0x0A.

        Ce raisonnement est-il plausible?

        • Partager sur Facebook
        • Partager sur Twitter
          30 novembre 2020 à 12:24:29

          Je viens de tester, j'ai bien 0x0D suivi de 0x0A
          • Partager sur Facebook
          • Partager sur Twitter
            30 novembre 2020 à 14:54:14

            rouloude a écrit:

            Je viens de tester, j'ai bien 0x0D suivi de 0x0A


            Salut.

            Alors je pense faire une erreur dans mon test.

            Peux-tu me partager le morceau de code qui t'a permis de tester afin que je trouve mon erreur?

            • Partager sur Facebook
            • Partager sur Twitter
              30 novembre 2020 à 15:21:06

              Le tien :

              #include <stdio.h>
              
              int main(void)
              {
                  int n;
                  FILE * sortie;
                  sortie = fopen ("test.txt", "w");
                  do
                  {
                      printf ("donnez un entier qui sera stocke a l'adresse %d : ", ftell(sortie));
                      scanf ("%d", &n);
                      if (n) fwrite (&n, sizeof(int), 1, sortie);
                  }
                  while (n);
              
                  fclose(sortie);
                  return 0;
              }

              Après je consultes avec un éditeur hexa !

              Mais pour ton problème d'origine c'est "wb" qu'il faut mettre comme mode d'ouverture de fichier.


              Edit : si tu n'as pas d'éditeur hexa :

              #include <stdio.h>
              
              int main(void)
              {
                  FILE * file = fopen ("test.txt", "rb");
              
                  unsigned char n;
              
                  while(fread (&n, 1, 1, file)) printf("0x%02X ", n);
              
                  fclose(file);
                  return 0;
              }




              -
              Edité par rouloude 30 novembre 2020 à 15:32:35

              • Partager sur Facebook
              • Partager sur Twitter
                30 novembre 2020 à 17:32:38

                Impeccable, tout est clair.

                Merci beaucoup de votre aide.

                • Partager sur Facebook
                • Partager sur Twitter

                Probleme décallage d'un octet fwrite/fread

                × 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