0

I have, I'm trying to read a binary file until end and print the result, I'm using and while with "feof" to read until end of file and printing each result, but I have a problem it is giving me double end result.

I'm still learning C, so I don't know why its giving me double end result, I have tried so many ways, but this was for me the best way and easiest that at least works, but now I'm stuck after 2 hours trying to fix it.

Result:

0
1
2
3
4
5
6
7
8
9
9

Expected:

0
1
2
3
4
5
6
7
8
9

My code:

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

int main()
{
    // https://www.aprendeaprogramar.com/cursos/verApartado.php?id=16007
    struct Datos
    {
        int cero;
        int uno;
        int dos;
        int tres;
        int cuatro;
        int cinco;
        int seis;
        int siete;
        int ocho;
        int nueve;
    };

    struct Datos datosEscrito = {0,1,2,3,4,5,6,7,8,9};

    FILE *fichero;

    fichero = fopen("tabla2.dat", "wb");

    fwrite(&datosEscrito, sizeof(datosEscrito), 1, fichero);

    fclose(fichero);

    int datoLeido;
    FILE *fichero2;

    fichero2 = fopen("tabla2.dat", "rb");

    while (!feof(fichero2))
    {
        fread(&datoLeido, sizeof(datoLeido), 1, fichero2);

        printf("%u", datoLeido);
        printf("\n");

    }

    fclose(fichero2);
}

PD: I don't want the code fix, I want to understand why is giving me double end and an approach to fix the error myself, or another way to do the same. Thanks for the help.

Code edit:

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

int main()
{

    FILE *fichero;

    fichero = fopen("tabla2.dat", "wb");

    int count=0;

    while (count != 10)
    {
        fwrite(&count, sizeof(count), 1, fichero);
        count++;
    }

    fclose(fichero);

    // PARTE LEER

    int datoLeido;
    FILE *fichero2;

    fichero2 = fopen("tabla2.dat", "rb");

    while (!feof(fichero2))
    {

        fread(&datoLeido, sizeof(datoLeido), 1, fichero2);

        printf("%u", datoLeido);
        printf("\n");

    }

    fclose(fichero2);

    return 0;
}
Vinanrra
  • 63
  • 7
  • 1
    Does this answer your question? [Why is “while ( !feof (file) )” always wrong?](https://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong) – kaylum Mar 31 '21 at 10:26
  • I already have read that, but I didn't understand, why I'm having double end, maybe because of this right? The conclusion is that there simply is no property like "I have data", since you cannot act meaningfully in response to any possible answer. So I need to create a for like he did at the example right? – Vinanrra Mar 31 '21 at 10:33
  • An additional problem in your wrong `while(!feof...)` loop is that you don't check the return value of `fread`. In the last loop cycle it would tell you that it has not read anything but detected EOF or error. When you write the binary representation of a structure as a whole to a file, then it is wrong to try to read it as individual fields one-by-one. This is undefined (or implementation dependent) behavior. In your case it may produce the expected result, but a structure can contain padding bytes with undefined value that are not part of any structure field. – Bodo Mar 31 '21 at 10:34
  • 1
    @Vinanrra The call to `feof` doesn't predict the future. It can't prevent you from trying to read the data that's not there. You don't check if `fread` succeeds, so when it fails, you still print out the data you read the last time through. Status reporting function (like `feof`) do not enable you to predict the future. You're thinking "`feof` will tell me whether or not a future read will succeed". No, it won't. – David Schwartz Mar 31 '21 at 10:38
  • *there simply is no property like "I have data"*. Yes there is. It's the return value of `fread`. – kaylum Mar 31 '21 at 10:39
  • @kaylum The return value of `fread` merely means "I *had* data". – Bodo Mar 31 '21 at 10:40
  • @Bodo I interpreted it to mean "I now have data in my variable". But yes, you could be right too. – kaylum Mar 31 '21 at 10:41
  • @kaylum The problem with this code is that it does not check `feof` before calling `printf` but after. The code calls `feof`, then `fread`, then `printf`, then `feof`. There is no call to `feof` between the call to `fread` and the call to `printf`. So the call to `printf` will happen whether the call to `fread` succeeds or hits the end of the file because it's not checked before printing. This code could only work if `feof` could predict whether a future read would hit the end of the file. It cannot predict the future. – David Schwartz Mar 31 '21 at 10:52
  • Going to check what u guys check, I have to remove the struck and add the data 1 by 1, and now I'm going to check that feof and fread problem, thanks for the help, lets see if I'm able to fix it. – Vinanrra Mar 31 '21 at 10:53

2 Answers2

0

The main problems in your program are that feof will only return a nonzero value when the previous fread (or other read operation) has detected an end-of-file condition and that you use the value even when fread would have told you by its return value that it has not read any data.

The functions feof and ferror are intended to distinguish between EOF and error after a failed file operation.

To fix the read loop you can use e.g.

    do
    {
        /* we expect to read 1 member */
        if(fread(&datoLeido, sizeof(datoLeido), 1, fichero2) == 1)
        {
            printf("%u", datoLeido);
            printf("\n");
        }
    } while ((!feof(fichero2)) && !ferror(fichero2));

There are more problems in your code.

  • The format %u corresponds to a type unsigned int. For int you should use %d.

  • You write the binary representation of a structure struct Datos to a file, then you read back individual values of type int.
    Although this seems to produce the expected result in your case it may not work in other cases. A structure can contain padding bytes that are not part of any structure field. These would have undefined values. In any case writing/reading the binary representation of variables is implementation-dependent. The data format may change when you use a different compiler (new version, different OS, different CPU...) or even with different compiler settings.

Bodo
  • 9,287
  • 1
  • 13
  • 29
  • Thanks for the help, I already solve the problem, but your code seems to be better, and yes I have change to %d forgot to change it, because I was using a struck. – Vinanrra Mar 31 '21 at 11:01
0

I was able to "fix" the problem, but i think it is a dirty fix, but at least works:

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

int main()
{

    FILE *fichero;

    fichero = fopen("tabla2.dat", "wb");

    int count=0;

    while (count != 10)
    {
        fwrite(&count, sizeof(count), 1, fichero);
        count++;
    }

    fclose(fichero);

    // PARTE LEER

    int datoLeido;
    FILE *fichero2;

    fichero2 = fopen("tabla2.dat", "rb");

    while (!feof(fichero2))
    {
        fread(&datoLeido, sizeof(datoLeido), 1, fichero2);

        if(!feof(fichero2))
        {
            printf("%d", datoLeido);
            printf("\n");
        }
    }

    fclose(fichero2);

    return 0;
}

Thanks to all for the help and @David Schwartz gave me the hint after reading that i am not checking if the file end it before print the data

Vinanrra
  • 63
  • 7