3

I consider reading file of unknown size that I know doesn't change size in the meantime. So I intend to use fstat() function and struct stat. Now I am considering what the st_size field really means and how should I use it.

If I get the file size's in this way, then allocate a buffer of that size and read exactly that size of bytes there seems to be one byte left over. I come to this conclusion when I used feof() function to check if there really nothing left in FILE *. It returns false! So I need to read (st_size + 1) and only than all bytes have been read and feof() works correctly. Should I always add this +1 value to this size to read all bytes from binary file or there is some hidden reason that this isn't reading to EOF?

struct stat finfo;
fstat(fileno(fp), &finfo);
data_length = finfo.st_size;

I am asking about this because when I add +1 then the number of bytes read by fread() is really -1 byte less, and as the last byte is inserted 00 byte. I could also before checking with feof() do something like this

fread(NULL, 1, 1, fp);

It is the real code, it is a little odd situation:

// reading png bytes from file
    FILE *fp = fopen("./test/resources/RGBA_8bits.png", "rb");

    // get file size from file info
    struct stat finfo;
    fstat(fileno(fp), &finfo);
    pngDataLength = finfo.st_size;

    pngData = malloc(sizeof(unsigned char)*pngDataLength);
    if( fread(pngData, 1, pngDataLength, fp) != pngDataLength) {
        fprintf(stderr, "%s: Incorrect number of bytes read from file!\n", __func__);
        fclose(fp);
        free(pngData);
        return;
    }

    fread(NULL, 1, 1, fp);
    if(!feof(fp)) {
        fprintf(stderr, "%s: Not the whole binary file has been read.\n", __func__);
        fclose(fp);
        free(pngData);
        return;
    }

    fclose(fp);
Toby Speight
  • 27,591
  • 48
  • 66
  • 103
Michał Ziobro
  • 10,759
  • 11
  • 88
  • 143
  • 1
    No, if the length of a a file has 1000 bytes, it's 1000 bytes, not 1001 nor 999. – Jabberwocky Oct 06 '16 at 12:44
  • Please show your code if you want more detailed answers. – Jabberwocky Oct 06 '16 at 12:45
  • now it works but I have to add this fread(NULL, 1, 1, fp); I can also change pngDataLength +1 in the first fread() but it returns just pngDataLength – Michał Ziobro Oct 06 '16 at 12:48
  • 1
    `fread(NULL, 1, 1, fp);` doesn't make sense, what are you expecting this to do ? – Jabberwocky Oct 06 '16 at 12:49
  • 1
    See http://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong – Klas Lindbäck Oct 06 '16 at 12:49
  • `fread(NULL, 1, 1, fp);` make sense it set `feof()` in the way it return `EOF` that I have correctly read all bytes from the file – Michał Ziobro Oct 06 '16 at 12:50
  • With `fread(NULL, 1, 1, fp);`, and code has not all ready read all the data, then code attempts to save a byte into `NULL`, which is UB. So anything may happen, even appear like no data was read. IOWs, do not code `fread(NULL, 1, 1, fp);`. Instead suggest `if (fgetc(fp) != EOF) { fprintf(stderr, ...` – chux - Reinstate Monica Oct 06 '16 at 13:42

1 Answers1

4

This behaviour is normal.

feof will return true only once you have tried to read beyond the file's end which you don't do as you read exactly the size of the file.

Jabberwocky
  • 48,281
  • 17
  • 65
  • 115