对大文件的便携式支持

Portable support for large files

我看了

而且我仍然不知道如何以可移植的方式了解大于 4 GB 的文件大小。

值得注意的是,合并一些答案无法为 Cygwin 编译,而其他答案则无法为 Linux。

事实证明,各种标准定义了相当多的功能:

  1. fseek/ftell

    由ANSI标准库定义。它几乎无处不在。它保证仅使用 32 位整数,但不是必需的(这意味着您可能会立即获得对大文件的支持)。

  2. fseeko/ftello

    这是由 POSIX 标准定义的。在许多平台上,根据 _FILE_OFFSET_BITS 的值,它会导致 off_t 被定义为 off64_tfseeko 被定义为 fseeko64 for _FILE_OFFSET_BITS=64.

  3. fseeko64/ftello64

    这是 fseekoftello 的 64 位等价物。我在任何标准中都找不到这方面的信息。

    Cygwin 不一致

    虽然它符合POSIX,但无论我在Cygwin下定义什么,我都无法编译fseeko,除非我使用--std=gnu++11,这显然是无意义的,因为它是一部分POSIX 而不是 GNU 扩展。那么给出了什么?根据 this discussion:

    64 bit file access is the natural file access type for Cygwin. off_t is 8 bytes. There are no foo64 functions for that reason. Just use fopen and friends and you get 64 bit file access for free.

    这意味着 #ifdef 对于 POSIX 平台上的 cygwin。

  4. _fseeki64 / _ftelli64

    这些由 Microsoft Visual C++ 定义,并且专门用于其编译器。显然它不支持上面列表中的任何其他内容(fseek 除外),因此您将需要 #ifdefs.

    编辑:实际上我建议不要使用它们和 I'm not the only one who thinks that。我经历了以下字面意思:

    1. wfopen二进制文件
    2. fwrite 10 个字节
    3. _ftelli64位置
    4. 它returns 12 个而不是 10 个字节

    看起来这个已经坏掉了。

  5. lseeklseek64

    由 POSIX 定义,这些将与使用 open()unistd.h 而不是 FILE* 结构打开的整数文件描述符一起使用。这些与 Windows 不兼容。同样,他们使用 off_t 数据类型。

  6. _lseek,_lseeki64

    这 Windows 相当于 lseek/lseek64。奇怪的是,_lseeki64 不使用 off_t 而是使用 __int64,所以你 知道 它可以处理大文件。整洁

  7. fsetpos/fgetpos

    虽然这些实际上非常便携,但它们几乎无法使用,因为它们对不透明结构而不是整数偏移量进行操作,这意味着您可以添加或减去它们,甚至可以导航到通过其他任何方式获得的文件中的特定位置比通过 fgetpos.

结论

所以为了让你的程序可移植,根据平台,你应该使用:

  • fseeko (POSIX) + 在 POSIX
  • 上定义 _FILE_OFFSET_BITS=64
  • fseek 对于 Cygwin 和默认实现
  • _lseeki64 for Windows - 或者,如果你设法绕过它 - _fseeki64.

使用_ftelli64的示例:

int64_t portable_ftell(FILE *a)
{
#ifdef __CYGWIN__
    return ftell(a);
#elif defined (_WIN32)
    return _ftelli64(a);
#else
    return ftello(a);
#endif
}

实际上,您可以检查函数是否使用您的构建系统编译,并相应地定义您自己的常量,例如 HAVE_FTELLO64,而不是检查对我来说总是脆弱的 #ifdefs。


请注意,如果您确实决定使用 lseek/_lseeki64 系列和数字文件描述符而不是 FILE* 结构,您应该注意 [=62] 之间的以下差异=]/fopen:

  • open 不使用缓冲,fopen 会。更少的缓冲意味着更差的性能。
  • open不能对文本文件进行换行,fopen可以。

    this question 中有更多详细信息。


参考文献: