Get Large File Size in C

2019-01-26 08:30发布

问题:

Before anyone complains of "duplicate", I've been checking SO quite thoroughly, but there seem to be no clean answer yet, although the question looks quite simple.

I'm looking for a portable C code, which is able to provide the size of a file, even if such a file is bigger than 4GB.

The usual method (fseek, ftell) works fine, as long as the file remains < 2GB. It's fairly well supported everywhere, so I'm trying to find something equivalent.

Unfortunately, the updated methods (fseeko, ftello) are not supported by all compilers. For example, MinGW miss it (and obviously MSVC). Furthermore, some comments make me believe that the new return type (off_t) does not necessarily support size > 2GB, it may depend on some external parameters, to be checked.

The unambiguous methods (fseeko64, ftello64) are not supported by MSVC. MS provides their equivalent, _fseeki64 & _ftelli64. This is already bad, but it becomes worse : some Linux configurations seem to badly support these functions during run time. For example, my Debian Squeeze on PowerPC, using GCC 4.4, will produce a "filesize" method using fseeko64 which always return 0 (while it works fine for Ubuntu64). MinGW seems to answer some random garbage above 2GB.

Well, I'm a bit clueless as far as portability is concerned. And if I need to make a bunch of #if #else, then why not go straight to the OS & compilers specifics methods in the first place, such as GetFileSize() for MSVC for example.

回答1:

You said it: there's no portable method; if I were you I'd just go with GetFileSize on Windows and stat on POSIX.



回答2:

You should be able to use stat64 on Linux and _stat64 on Windows to get file size information for files over 2 GBs, and both functions are very similar in usage. You can also use a couple of #defines to use stat64 on Windows too:

#if __WIN32__
#define stat64 _stat64
#endif

However, although this should work, it should be noted that the _stat family of functions on Windows is really just a wrapper around other functions, and will add additonal resources and time overhead.



回答3:

int ch;
FILE *f = fopen("file_to_analyse", "rb");
/* error checking ommited for brevity */
unsigned long long filesize = 0; /* or unsigned long for C89 compatability*/
while ((ch = fgetc(f)) != EOF) filesize++;
fclose(f);
/* error checking ommited for brevity */


回答4:

I have implemented and tested the following:

#if __WIN32__
#define stat64 _stat64
#endif

using MinGW64 gcc compiler 4.8.1 and Linux gcc 4.6.3 compiles and works.

On OSX, no redefinition of stat required.

for lstat and fstat functions I expect similar macro #defines to work.



回答5:

What about using lseek() (or _lseek()) with SEEK_END? It returns the offset sought to.

Under linux _FILE_OFFSET_BITS needs to be defined to 64 for lseek() to return 64bit values (which should be the default anyhow).



回答6:

#include sys/stat.h

off_t fsize(const char *filename) {
    struct stat st; 

    if (stat(filename, &st) == 0)
        return st.st_size;

    return -1; 
}