0
votes

I have a binary file from which I need to read 32 bit patterns- In the event if the EOF is reached such that its less than 32 bits - I need to error out saying unexpected eof else just break. I tried a lot but I am unable to get the incomplete bytes detecting part working. Can someone provide some pointer how to achieve it ? I did thought of exploring one byte at a time byte[0] and evaluating if its EOF but didnt work.

   for (;;)
   {
     bytes_read = fread(buffer, 4, 1, inFile);
     if (bytes_read == 1)
     {
      // perform the task
     }
     else
     {
         // detect if its incomplete sequence or EOF and output appropriately
     }
   }

P.S : Editing fread as per comment -

2
Why are you using sizeof(char) as the number of items to read?Barmar
sizeof(char) is always 1. EOF token doesn't fit into a char. You're trying to read more than one char and still comparing if you only read one?Sami Kuhmonen
You do not have "hexadecimal" in the file; you have binary. Hexadecimal consists of text like 3D0F, which is four characters denoting 16 bits or two bytes. Also note that sizeof (char) is 1 by definition, and it is inappropriate to use it for another reason: the third argument to fread represents the number of elements to read, of the size given by the second argument. sizeof (char) isn't a good way to express the concept of "give me one element".Kaz
@Kaz - Thanks for making me aware about the binary part and differentiation with hexadecimal - I get the fread part - problem is pubs.opengroup.org/onlinepubs/009695399/functions/fread.html - doesnt mention do's and don'ts of how to represent the 1 - so I naively chose sizeof(char) -oneday
@SamiKuhmonen - Can you please put a snippet of what would be best way to achieve it - as I am unable to get my head around it .oneday

2 Answers

1
votes

Your code tells fread to read one record, containing 4 bytes, from the file. If the record is incomplete, it will return 0 (0 records read, error). If the record is missing (at end of file), it will also return 0 (0 records read, normal situation). You must adjust your code to distinguish these cases, by having fread return 4 (bytes) instead.

If it's impossible to read 4 bytes at the end of file, you want fread to output less than 4. To have this behavior, you should tell fread to read in units of 1 byte:

bytes_read = fread(buffer, 1, 4, inFile);

Then look at the number:

if (bytes_read == 4)
{
    // perform the task
}
else if (bytes_read > 0)
{
    // bad file format - not a multiple of 4 bytes
}
else if (bytes_read == 0)
{
    break; // success
}
else // bytes_read = -1
{
    // general file error
}
0
votes

fread doesn't return the number of bytes read, it returns the number of items, whose size is given in the second argument, were read. Since you're asking for it to read 1 item; if it encounters EOF before reading all the bytes of the item, it should return 0.

Although sizeof(char) is defined to be 1, it's not appropriate to use it in a context where you're not actually referring to the size of something. In this case, it's just a count, so you should use 1.

size_t items_read = fread(buffer, sizeof(unsigned long), 1, inFile);
if (items_read == 1) {
    // perform the task
} else if (feof(inFile)) {
    // got EOF before reading the last number
} else if (ferror(inFile)) {
    // got an error
}