如何:C中的跨操作系统大文件IO?

时间:2014-04-23 23:28:26

标签: c file io

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

目标:我试图让“单向”(最可能是基于宏的)允许32位AND 64位具有大文件支持。理想情况下,使用typedef,#ifdef,#(n)定义等宏包装器可以允许以#include库或一组定义的宏的形式支持基本的大文件。

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

问题:在我的键盘和几本教科书上敲击之后,我决定对你们所有人进行调查:你们这些人/女孩如何实现跨操作系统文件支持大文件的I / O?

P.S。我有研究链接:

3 个答案:

答案 0 :(得分:1)

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

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

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

答案 1 :(得分:0)

尽管我们都喜欢讨厌M $因为他们糟糕的标准一致性,但这个实际上是ISO C委员会的错。最初,他们将size_t用于所有文件参数,但size_t是根据ALU /内存架构选择的,而不是基于操作系统文件处理功能。当每个人都切换到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()在大型文件&gt; 2GB的MSVC上工作,但ftell()和fseek()没有,因为API没有正确设计。

答案 2 :(得分:0)

在Windows中没有选项的情况下完全

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