I looked at
and I still don't know how to get to know size of file larger than 4 gb in a portable way.
Notably, incorporating some of the answers failed compiling for Cygwin, while the others failed for Linux.
I looked at
and I still don't know how to get to know size of file larger than 4 gb in a portable way.
Notably, incorporating some of the answers failed compiling for Cygwin, while the others failed for Linux.
Copyright © 2021 Jogjafile Inc.
Turns out there are quite a few functions defined by various standards:
fseek/ftellIt's defined by ANSI standard library. It's available virtually everywhere. It is guaranteed to work with 32-bit integers only, but it isn't required to (meaning you might get support for large files out of the box).
fseeko/ftelloThis is defined by POSIX standard. On many platforms, depending on value of
_FILE_OFFSET_BITSit will causeoff_tto be defined asoff64_tandfseekoasfseeko64for_FILE_OFFSET_BITS=64.fseeko64/ftello64This is the 64-bit equivalent of
fseekoandftello. I couldn't find information on this in any standard.Cygwin inconsistency
While it conforms to POSIX, I can't compile the
fseekono matter what I define under Cygwin, unless I use--std=gnu++11which is obviously nonsense, since it's part of POSIX rather than a GNU extension. So what gives? According to this discussion:This means
#ifdeffor cygwin on POSIX platforms._fseeki64/_ftelli64These are defined by Microsoft Visual C++ and are exclusively used with their compiler. Obviously it doesn't support anything else from the list above (other than
fseek), so you're going to need#ifdefs.EDIT: I actually advise against using them and I'm not the only one who thinks that. I experienced literally following:
wfopena file in binary modefwrite10 bytes worth to it_ftelli64the positionLooks like this is horribly broken.
lseekandlseek64Defined by POSIX, these are to be used with integer file descriptors opened with
open()fromunistd.hrather thanFILE*structs. These are not compatible with Windows. Again, they useoff_tdata type._lseek,_lseeki64This is Windows equivalent of
lseek/lseek64. Curiously,_lseeki64doesn't useoff_tand uses__int64instead, so you know it'll work with big files. Neat.fsetpos/fgetposWhile these are actually pretty portable, they're almost unusable, since they operate on opaque structures rather than integer offsets, meaning you can add or subtract them, or even navigate to certain position in file obtained by any means other than through
fgetpos.Conclusion
So to make your program portable, depending on the platform, you should use:
fseeko(POSIX) + define_FILE_OFFSET_BITS=64on POSIXfseekfor Cygwin and for default implementation_lseeki64for Windows - or, if you manage to work your way around it -_fseeki64.An example that uses
_ftelli64:In reality, instead of checking
#ifdefs which always looked fragile to me, you could check if the functions compile using your build systems, and define your own constants such asHAVE_FTELLO64accordingly.Note that if you indeed decide to use
lseek/_lseeki64family and numeric file descriptors rather than theFILE*structures, you should be aware of following differences betweenopen/fopen:opendoesn't use buffering,fopendoes. Less buffering means worse performance.opencan't perform newline conversions for text files,fopencan.More details in this question.
References: