How to get file size in ANSI C without fseek and ftell? How to get file size in ANSI C without fseek and ftell? c c

How to get file size in ANSI C without fseek and ftell?


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, or offset shall be a value returned by an earlier successful call to the ftell function on a stream associated with the same file and whence shall be SEEK_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 a whence value of SEEK_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.


Use fstat - requires the file descriptor - can get that from fileno from the FILE* - Hence the size is in your grasp along with other details.

i.e.

fstat(fileno(filePointer), &buf);

Where filePointer is the FILE *

and

buf is

struct stat {    dev_t     st_dev;     /* ID of device containing file */    ino_t     st_ino;     /* inode number */    mode_t    st_mode;    /* protection */    nlink_t   st_nlink;   /* number of hard links */    uid_t     st_uid;     /* user ID of owner */    gid_t     st_gid;     /* group ID of owner */    dev_t     st_rdev;    /* device ID (if special file) */    off_t     st_size;    /* total size, in bytes */    blksize_t st_blksize; /* blocksize for file system I/O */    blkcnt_t  st_blocks;  /* number of 512B blocks allocated */    time_t    st_atime;   /* time of last access */    time_t    st_mtime;   /* time of last modification */    time_t    st_ctime;   /* time of last status change */};