Determining File Size in C
When working with files in C, a common task is to determine the file’s size. This is often necessary before allocating memory to read the entire file content into a buffer. Here, we’ll explore several methods to achieve this, covering approaches using standard C library functions and POSIX-specific functions.
Using fseek
and ftell
The fseek
and ftell
functions provide a portable way to determine file size. fseek
moves the file pointer to a specific position, and ftell
returns the current position of the file pointer. By seeking to the end of the file and then calling ftell
, we can obtain the file size.
#include <stdio.h>
long get_file_size(FILE *fp) {
if (fseek(fp, 0, SEEK_END) != 0) {
// Error handling: fseek failed
return -1; // Or other appropriate error value
}
long size = ftell(fp);
if (size == -1) {
// Error handling: ftell failed
return -1; // Or other appropriate error value
}
return size;
}
int main() {
FILE *fp = fopen("my_file.txt", "r");
if (fp == NULL) {
perror("Error opening file");
return 1;
}
long size = get_file_size(fp);
if (size != -1) {
printf("File size: %ld bytes\n", size);
}
//Important: Rewind the file pointer to the beginning before reading!
rewind(fp);
fclose(fp);
return 0;
}
Explanation:
fseek(fp, 0, SEEK_END)
: This moves the file pointer to the end of the file.fp
is the file pointer,0
represents an offset of zero bytes, andSEEK_END
indicates that the offset is relative to the end of the file.ftell(fp)
: This returns the current position of the file pointer, which, afterfseek
, corresponds to the file size in bytes.rewind(fp)
: This is crucial. After determining the file size, the file pointer is at the end of the file. If you intend to read the file content, you must rewind the file pointer to the beginning usingrewind(fp)
before reading.
Important Considerations:
- Error Handling: The
fseek
andftell
functions can return errors. Always check the return values to ensure the operations were successful. - Binary vs. Text Mode: The file should be opened in the appropriate mode (e.g., "rb" for reading in binary mode) depending on the file type.
Using stat
, fstat
, and lseek
(POSIX Systems)
For POSIX-compliant systems (Linux, macOS, etc.), you can leverage the stat
, fstat
, and lseek
functions for more direct file size retrieval.
stat(filename, &statbuf)
: This function retrieves file information (including size) from a file specified by its name (filename
). It populates astruct stat
(defined in<sys/stat.h>
) with the file’s attributes.fstat(fd, &statbuf)
: This is similar tostat
, but it operates on a file descriptor (fd
) instead of a filename. You obtain a file descriptor by opening a file withopen()
.lseek(fd, 0, SEEK_END)
: This function, in combination with a file descriptor, moves the file offset to the end of the file and returns the new offset, which is the file size.
Here’s an example using stat
:
#include <stdio.h>
#include <sys/stat.h>
int main() {
struct stat file_info;
if (stat("my_file.txt", &file_info) == 0) {
printf("File size: %lld bytes\n", (long long)file_info.st_size);
} else {
perror("Error getting file information");
return 1;
}
return 0;
}
Explanation:
struct stat file_info
: Declares astruct stat
variable to store the file’s information.stat("my_file.txt", &file_info)
: Calls thestat
function to retrieve the file information for "my_file.txt" and store it infile_info
.file_info.st_size
: Accesses thest_size
member of thestruct stat
to obtain the file size.
Choosing the Right Method
- For maximum portability, the
fseek
andftell
method is preferred. It works on a wider range of systems. - If you are developing exclusively for POSIX-compliant systems, using
stat
,fstat
, orlseek
can be more efficient.stat
is particularly useful if you need other file attributes besides the size. - If you already have a file descriptor (e.g., from
open()
),fstat
orlseek
are the natural choices.
Remember to always handle potential errors when working with file operations and rewind the file pointer if necessary before reading the file content.