While looking for ways to find the size of a file given a FILE*
, I came across this article advising against it. Instead, it seems to encourage using file descriptors and fstat
.
However I was under the impression that fstat
, open
and file descriptors in general are not as portable (After a bit of searching, I've found something to this effect).
Is there a way to get the size of a file in ANSI C while keeping in line with the warnings in the article?
Right-click the file and click Properties. The image below shows that you can determine the size of the file or files you have highlighted from in the file properties window. In this example, the chrome. jpg file is 18.5 KB (19,032 bytes), and that the size on disk is 20.0 KB (20,480 bytes).
The filesize() function returns the size of a file.
The idea is to use fseek() in C and ftell in C. Using fseek(), we move file pointer to end, then using ftell(), we find its position which is actually size in bytes.
In standard C, the fseek
/ftell
dance is pretty much the only game in town. Anything else you'd do depends at least in some way on the specific environment your program runs in. Unfortunately said dance also has its problems as described in the articles you've linked.
I guess you could always read everything out of the file until EOF and keep track along the way - with fread()
for example.
The article claims fseek(stream, 0, SEEK_END)
is undefined behaviour by citing an out-of-context footnote.
The footnote appears in text dealing with wide-oriented streams, which are streams that the first operation that is performed on them is an operation on wide-characters.
This undefined behaviour stems from the combination of two paragraphs. First §7.19.2/5 says that:
— Binary wide-oriented streams have the file-positioning restrictions ascribed to both text and binary streams.
And the restrictions for file-positioning with text streams (§7.19.9.2/4) are:
For a text stream, either
offset
shall be zero, oroffset
shall be a value returned by an earlier successful call to theftell
function on a stream associated with the same file andwhence
shall beSEEK_SET
.
This makes fseek(stream, 0, SEEK_END)
undefined behaviour for wide-oriented streams. There is no such rule like §7.19.2/5 for byte-oriented streams.
Furthermore, when the standard says:
A binary stream need not meaningfully support
fseek
calls with awhence
value ofSEEK_END
.
It doesn't mean it's undefined behaviour to do so. But if the stream supports it, it's ok.
Apparently this exists to allow binary files can have coarse size granularity, i.e. for the size to be a number of disk sectors rather than a number of bytes, and as such allows for an unspecified number of zeros to magically appear at the end of binary files. SEEK_END
cannot be meaningfully supported in this case. Other examples include pipes or infinite files like /dev/zero
. However, the C standard provides no way to distinguish between such cases, so you're stuck with system-dependent calls if you want to consider that.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With