HOWTO:C中的跨操作系统大文件IO



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

目标:我正在尝试"单向"(很可能是基于宏的),以允许32位AND 64位具有大文件支持。理想情况下,定义了typedef、#ifdef、#(n)等,宏包装器可以允许以#include库或一组定义的宏的形式支持基本的大文件。

研究:POSIX的文件操作在32位和64位IO的BSD/Mac/Linux上表现出色,文件大小超过了典型的2^31大小,但即使在Windows上使用clang或mingw,我也无法利用这些调用,因为M$对POSIX的愚蠢实现(如果我们想这么称呼它的话…),但就所使用的方法和数据类型而言,这与POSIX的open()/read()/write()/close()等完全不同。

问题:在我的头撞到键盘和几本课本之后,我决定对你们所有人进行民意调查,看看:你们是如何完成支持大文件的跨操作系统文件I/O的

附言:我有研究链接:

  • http://msdn.microsoft.com/en-us/library/windows/desktop/bb540534(v=vs.85).aspx
  • 在C/C中获取文件大小的可移植方法++
  • 如何便携式打开大文件支持
  • http://mingw-users.1079350.n2.nabble.com/not-obvious-how-to-compile-programs-for-large-files-td5699144.html
  • http://www.viva64.com/en/l/full/
  • https://developer.apple.com/library/mac/documentation/Darwin/Conceptual/64bitPorting/HighLevelAPIs/HighLevelAPIs.html
  • https://www.securecoding.cert.org/confluence/display/c/FIO19-C.+Do+not+use+fseek%28%29+and+ftell%28%29]to+compute+the+size+of+a+regular+file
  • https://www.securecoding.cert.org/confluence/display/c/FIO03-C.+做+不做+做+假设+关于+fopen%28%29+和+文件+创建
  • https://en.wikipedia.org/wiki/Large_file_support

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

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

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

尽管我们都很讨厌M$糟糕的标准合规性,但这实际上是ISO C委员会的错。最初,他们将size_t用于所有文件参数,但size_t是根据ALU/内存体系结构而非操作系统文件处理能力选择的。当每个人都切换到64位CPU时,MS坚持使用32位长的CPU,他们完全可以这样做,而且仍然是一致的,但现在他们的文件比他们最大的算术类型更大。

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

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

为了证明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设计不正确。

在Windows:中没有选项,您并非完全

  • _fseeki64
  • _ftelli64

在Linux中,您可以使用-D_FILE_OFFSET_BITS=64#define _FILE_OFFSET_BITS 64可能工作,不确定)和fseeko/ftello。许多系统也有fseeko64ftello64),它们工作与#define无关。

相关内容

  • 没有找到相关文章

最新更新