【问题标题】:HOWTO: Cross-Operating-System Large File IO in C?如何:C 中的跨操作系统大文件 IO?
【发布时间】:2014-04-23 23:28:26
【问题描述】:

简而言之: C 中的跨操作系统、大文件支持非常可怕。

目标:我正在尝试使用“一种方式”(最有可能基于宏)来允许 32 位和 64 位支持大文件。理想情况下,使用 typedef、#ifdef、#(n)defined 等,宏包装器可以允许以 #include 库或一组已定义宏的形式支持基本的大文件。

研究: POSIX 的文件操作在 32 位和 64 位 IO 的 BSD/Mac/Linux 上表现出色,文件大于典型的 2^31 大小,但即使在 Windows 上使用 clang 或 mingw由于 M$ 对 POSIX 的愚蠢实现,我无法利用这些调用(如果这就是我们想要调用的......)。我倾向于在 Windows 上使用 CreateFile()、ReadFile()、WriteFile(),但这在方法和数据类型方面与 POSIX 的 open()/read()/write()/close()/etc 完全不同用过。

问题:在敲了敲键盘和几本教科书之后,我决定对你们所有人进行投票,看看:你们是如何完成跨操作系统文件的支持大文件的 I/O?

附:我有研究链接:

【问题讨论】:

    标签: c file io


    【解决方案1】:

    看来,你需要一个不同版本的mingw:

    http://mingw-w64.sourceforge.net/

    w64 变体甚至在 32b 窗口上也支持 linux 兼容的大文件。

    【讨论】:

      【解决方案2】:

      尽管我们都喜欢讨厌 M$ 的糟糕标准一致性,但这实际上是 ISO C 委员会的错。最初他们将 size_t 用于所有文件参数,但 size_t 是基于 ALU/内存架构而不是基于 OS 文件处理能力选择的。当每个人都切换到 64 位 CPU 时,MS 坚持使用 32 位长度,他们完全可以这样做并且仍然符合要求,但现在他们的文件比他们最大的算术类型大。

      请注意,这最终在 C99 中得到解决,但 MSVC C99 支持基本上不存在。

      然而,在内部,它们确实使用 64 位指针来跟踪您在文件中的位置。问题是由于不幸的 cstdlib API,您不能对大于 32 位的任何内容使用“fseek”或“ftell”。

      为了证明 Windows 确实使用了 64 位文件指针,这段代码在使用 MSVC++ 编译时实际上会按预期工作,并会在您的硬盘驱动器上生成一个 40GB 的文件(无符号长整数为 32 位)。

      #include <stdio.h>
      
      int main(int argc, char **argv) {
          FILE *my_file;
          unsigned long i, j;
      
          my_file = fopen("bigfile.bin", "wb");
      
          for(i = 0; i < 10; i++) {
              for(j = 0; j < (1024 * 1024 * 1024); j++) {
                  fwrite(&j, sizeof(j), 1, my_file);
              }
          }
      
          fclose(my_file);
      
          return 0;
      }
      

      那么这对您有什么帮助?嗯,MS 提供了自己的非标准 API,允许 64 位 fseek() 和 ftell()

      https://msdn.microsoft.com/en-us/library/75yw9bf3.aspx

      不过,您实际上可以使用常规 fseek() 以增量方式移动文件指针...基本上如果您这样做:

      fseek(my_file, 0, SEEK_SET);
      for(i = 0; i < 10; i++) {
          fseek(my_file, (1024 * 1024 * 1024), SEEK_CUR);
      }
      

      它将有效地将文件指针移动到 10GB 标记。

      虽然使用 ftell(),但如果不使用 MS API,您可能会被搞砸。

      TL;DR - fopen()、fread() 和 fwrite() 可以在大于 2GB 的大文件的 MSVC 上工作,但 ftell() 和 fseek() 不能,因为 API 设计不正确。

      【讨论】:

        【解决方案3】:

        你不是完全没有Windows中的选项:

        在 Linux 中,您可以使用 -D_FILE_OFFSET_BITS=64#define _FILE_OFFSET_BITS 64 可能工作,不确定)和 fseeko / ftello。许多系统还具有fseeko64ftello64),无论#define如何,它们都可以正常工作。

        【讨论】:

          猜你喜欢
          • 2013-12-05
          • 2013-07-29
          • 1970-01-01
          • 2020-01-16
          • 1970-01-01
          • 2014-05-05
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多