Michał Ziobro Michał Ziobro - 2 months ago 7
C Question

C using fstat() to read size of file

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);

Answer

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.