I'm not sure why fseek()
/ftell()
is taught as a generic way to get the size of a file. It only works because an implementation defines it to work. POSIX does, for one. Windows does, also, for binary streams - but not for text streams.
It's wrong to not add a caveat or warning to, "This is how you get the number of bytes in a file." Because when a programmer first gets on a system that doesn't define fseek()
/ftell()
as byte offsets, they're going to have problems. I've seen it.
"But I was told this is how you can always do it."
"Well, no. Whoever taught you was wrong."
Because it is impossible to use fseek()
/ftell()
to get the size of a file in strictly-conforming C code.
For a binary stream, 7.21.9.2 The fseek
function, paragraph 3 of the C standard:
For a binary stream, the new position, measured in characters from the
beginning of the file, is obtained by adding offset
to the
position specified by whence
. The specified position is the
beginning of the file if whence
is SEEK_SET
, the current value of
the file position indicator if SEEK_CUR , or end-of-file if
SEEK_END
. A binary stream need not meaningfully support fseek
calls with a whence
value of SEEK_END
.
Footnote 268 specifically states:
Setting the file position indicator to end-of-file, as with
fseek(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.
So you can't seek the the end of a binary stream to get a file's size in bytes.
And for a text stream, 7.21.9.4 The ftell
function, paragraph 2 states:
The ftell
function obtains the current value of the file position
indicator for the stream pointed to by stream
. For a binary
stream, the value is the number of characters from the
beginning of the file. For a text stream, its file position
indicator contains unspecified information, usable by the fseek
function for returning the file position indicator for the stream to
its position at the time of the ftell
call; the difference
between two such return values is not necessarily a meaningful
measure of the number of characters written or read.
So you can't use ftell()
on a text stream to get a byte count.
The only strictly-conformant approach that I'm aware of to get the number of bytes in a file is to read them one-by-one with fgetc()
and count them.