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.fpis the file pointer,0represents an offset of zero bytes, andSEEK_ENDindicates 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
fseekandftellfunctions 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 statvariable to store the file’s information.stat("my_file.txt", &file_info): Calls thestatfunction to retrieve the file information for "my_file.txt" and store it infile_info.file_info.st_size: Accesses thest_sizemember of thestruct statto obtain the file size.
Choosing the Right Method
- For maximum portability, the
fseekandftellmethod is preferred. It works on a wider range of systems. - If you are developing exclusively for POSIX-compliant systems, using
stat,fstat, orlseekcan be more efficient.statis particularly useful if you need other file attributes besides the size. - If you already have a file descriptor (e.g., from
open()),fstatorlseekare 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.