To Read a Chunk a Data

Say you must read 2048 bytes from a file. Which of the following fread() statements works for you: A, B, both, or neither?

A. c = fread( buffer, 2048, 1, fh);

B. c = fread( buffer, 1, 2048, fh);

The difference between these statements is the order of the second and third arguments. As a review, the second argument is the size of data chunk to read and the third is the number of chunks. To read 2048 bytes, it seems like either choice works.

For option A, the chunk size is 2048 bytes and one chunk is read. That means 2048 bytes are read, right?

For option B, the chunk size is one byte and the number of chunks to read is 2048. Again, the total is 2048. So what’s the difference?

The difference is that option B performs as expected. Option A reads only one byte. Here’s sample code for option A:

#include <stdio.h>

int main()
{
    char filename[] = "declaration.txt";
    char buffer[2048];
    FILE *fh;
    int r;

    /* open the file */
    fh = fopen(filename,"r");
    if(!fh)
    {
        fprintf(stderr,"Unable to open %s\n",filename);
        return(1);
    }

    r = fread( buffer, 2048, 1, fh );
    printf("%d bytes read\n",r);

    fclose(fh);
    return(0);
}

This code opens the file declaration.txt for reading at Line 11. The fread() function at Line 18 seems like it would pull 2048 characters (one 2048-byte chunk) from the file, a value returned in variable r. But when the code runs, you see this output:

1 bytes read

Given the description from the fread() function’s man page, you would think the statement would read 2048 bytes: The size argument is 2048 and the nitems argument is 1. Even if you cast the value 2048 as a size_t data type, only one byte is read.

When the arguments are swapped, however, the program runs as expected:

#include <stdio.h>

int main()
{
    char filename[] = "declaration.txt";
    char buffer[2048];
    FILE *fh;
    int r;

    /* open the file */
    fh = fopen(filename,"r");
    if(!fh)
    {
        fprintf(stderr,"Unable to open %s\n",filename);
        return(1);
    }

    r = fread( buffer, 1, 2048, fh );
    printf("%d bytes read\n",r);

    fclose(fh);
    return(0);
}

The only change made above is to Line 18: arguments 1 and 2048 are swapped. Here’s the output:

2048 bytes read

Of course, the proper way to write the statement is:

r = fread( buffer, sizeof(char) , 2048, fh );

The declaration.txt file is text, so the data chunk being read is a character; the data-chunk size is one character.

As a confession, the reason I wrote this post is because this exact puzzle recently tripped me up. I couldn’t understand why the fread() function was gobbling up only one byte from a file. Yet, when I swapped the second and third arguments, the code ran as expected. Weird, but important.

2 thoughts on “To Read a Chunk a Data

  1. I think both of these work correctly. One reads 2048 items of 1 byte each, and the other reads 1 item of 2048 bytes. Try printing the buffer rather than the return value of fread.

  2. I see that it does: The data is read, which is something I didn’t even check for. The problem I ran into is when reading the last n bytes of the file. Because r returns 1 regardless (when the function is misstated), the actual size of data read is inaccurate. For the program I was running, I was unable to calculate the final buffer size, which resulted in an overflow.

    My advice would be that regardless of the internal performance, properly formatting the function is vital if you’re using the return data to reallocate a buffer.

Leave a Reply