对大文件的便携式支持

Portable support for large files

本文关键字:便携式 支持 文件      更新时间:2023-10-16

我看了看

  • 而这个
  • 而这个

我仍然不知道如何以便携式方式了解大于 4 GB 的文件大小。

值得注意的是,合并一些答案在Cygwin编译时失败了,而其他答案在Linux上失败了。

事实证明,有相当多的函数由各种标准定义:

  1. fseek/ftell

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

  2. fseeko/ftello

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

  3. fseeko64/ftello64

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

    天鹅座不一致

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

    64 位文件访问是自然的 Cygwin 的文件访问类型。 off_t为 8 个字节。 没有 foo64 函数因此而起作用。 只需使用fopen和朋友,你就会得到64 免费访问位文件。

    这意味着在POSIX平台上#ifdef cygwin。

  4. _fseeki64/_ftelli64

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

    编辑:我实际上建议不要使用它们,我不是唯一一个这么认为的人。我从字面上经历了以下经历:

    1. 在二进制模式下wfopen文件
    2. fwrite 10 字节的价值
    3. _ftelli64职位
    4. 它返回 12 个字节而不是 10 个字节

    看起来这已经坏得可怕了。

  5. lseeklseek64

    由 POSIX 定义,这些描述符将与使用unistd.h open()而不是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适用于 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
}

实际上,与其检查对我来说总是脆弱#ifdef,不如检查函数是否使用构建系统进行编译,并相应地定义自己的常量,例如HAVE_FTELLO64


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

  • open不使用缓冲,fopen使用缓冲。缓冲越少意味着性能越差。
  • open无法对文本文件执行换行符转换,fopen可以。

    这个问题中有更多详细信息。


引用:

  • http://www.lix.polytechnique.fr/~liberti/public/computing/prog/c/C/FUNCTIONS/funcref.htm#stdio
  • http://pubs.opengroup.org/onlinepubs/9699919799/functions/fseek.html
  • http://pubs.opengroup.org/onlinepubs/009695399/functions/open.html
  • http://pubs.opengroup.org/onlinepubs/009695399/functions/lseek.html
  • http://man7.org/linux/man-pages/man2/lseek.2.html
  • https://msdn.microsoft.com/en-us/library/75yw9bf3.aspx
  • http://www.cplusplus.com/reference/cstdio/fgetpos/
  • http://pubs.opengroup.org/onlinepubs/009695399/functions/fgetpos.html