With some caveats, you can read the entire file into an appropriately-sized buffer in one fell swoop using the fread()
function.
The following code outlines how to open the file, determine its size, allocate a buffer of that size, then read the file's data (all of it) into that buffer. But note the caveats about the fseek
and ftell
functions (discussed afterwards):
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char* filename = "MyFile.txt"; // Or whatever
FILE* fp = fopen(filename, "rb"); // Open in binary mode
int seek = fseek(fp, 0, SEEK_END); // CAVEAT: Files in BINARY mode may not support SEEK_END ...
if (seek != 0) {
printf("Cannot fseek on binary file!\n");
fclose(fp);
return 1;
}
size_t filesize = (size_t)ftell(fp); // ... but this is not reliable if opened in TEXT mode!
char* filedata = calloc(filesize + 1, 1); // Add 1 for the terminating "nul" character
rewind(fp);
fread(filedata, 1, filesize, fp); // Read whole file
// Clean up ...
fclose(fp);
free(filedata);
return 0;
}
Caveats:
Note that files opened in BINARY mode (as in the "rb"
mode argument I gave in the fopen()
call) are not required to support the SEEK_END
origin in calls to fseek()
; if this is the case on your platform, then this answer offers some alternatives to determine the file's size. From cppreference:
… Binary streams are not required to support SEEK_END, in
particular if additional null bytes are output.
However, on the other hand, opening the file in TEXT mode (using "rt"
) will make the call to ftell
effectively meaningless, in terms of the required size for your input buffer and the value specified to fread
; from cppreference:
If the stream is open in text mode, the value returned by this
function is unspecified and is only meaningful as the input to
fseek().
Also note that, as pointed out in the comments, the fseek()
and ftell()
functions will fail if the size of the file is larger than the maximum value that can be stored in a long int
variable; to handle such cases, you can use the (platform-dependent) 64-bit equivalents, as I described in an answer I posted some time ago.