In C, we can find the size of file using fseek()
function. Like,
if (fseek(fp, 0L, SEEK_END) != 0)
{
// Handle repositioning error
}
So, I have a question, Is it recommended method for computing the size of a file using fseek()
and ftell()
?
If you're on Linux or some other UNIX like system, what you want is the
stat
function:On Windows under MSVC, you can use
_stati64
:Unlike using
fseek
, this method doesn't involve opening the file or seeking through it. It just reads the file metadata.Well, you can estimate the size of a file in several ways:
read(2)
the file from the beginning to the end, and the number or chars read is the size of the file. This is a tedious way of getting the size of a file, as you have to read the whole file to get the size. But if the operating system doesn't allow to position the file pointer arbitrarily, then this is the only way to get the file size.lseek(2)
you showed in the question, but be careful that you have to do the system call twice, as the value returned is the actual position before moving the pointer to the desired place.stat(2)
system call, that will tell you all the administrative information of the file, like the owner, group, permissions, size, number of blocks the file occupies in the disk, disk this file belongs to, number of directory entries pointing to it, etc. This allows you to get all this information with only one syscall.Other methods you point (like the use of the
ftell(3)
stdio library call) will work also (with the same problem that it results in two system calls to set and retrieve/restore the file pointer) but have the problem of involving libraries that probably you are not using for anything else. It should be complicated to get aFILE *
pointer (e.g.fdopen(3)
) on aint
file descriptor, just to be able to use theftell(3)
function on it (twice), and thenfclose(3)
it again.The
fseek()/ftell()
works sometimes.Problems.
If the file size exceeds about
LONG_MAX
,long int ftell(FILE *stream)
response is problematic.If the file is opened in text mode, the return value from
ftell()
may not correspond to the file length. "For a text stream, its file position indicator contains unspecified information," C11dr §7.21.9.4 2If the file is opened in binary mode,
fseek(fp, 0L, SEEK_END)
is not well defined. "Setting the file position indicator to end-of-file, as withfseek(file, 0, SEEK_END)
, has undefined behavior for a binary stream (because of possible trailing null characters) or for any stream with state-dependent encoding that does not assuredly end in the initial shift state." C11dr footnote 268. @Evert This most often applies to earlier platforms than today, but it is still part of the spec.If the file is a stream like a serial input or
stdin
,fseek(file, 0, SEEK_END)
makes little sense.The usual solution to finding file size is a non-portable platform specific one. Example good answer @dbush.
Note: If code attempts to allocate memory based on file size, the memory available can easily be exceeded by the file size.
Due to these issues, I do not recommend this approach.
Typically the problem should be re-worked to not need to find the file size, but to grow the data as more input is processed.
LL disclaimer: Note that C spec footnotes are informative and so not necessarily normative.
The best method in my opinion is
fstat()
: https://linux.die.net/man/2/fstat