2012-01-16 62 views
5

我需要使用C访问大于2GB的文件。在程序的一次运行过程中,将从该文件读取可变数量的字节并保存下一个位置的位置。在程序的下一次运行过程中,读取文件位置并从该位置开始读取大量字节。在C中访问大文件

复杂的是,有时文件可能会被压缩,通过复制它到一个新的文件,更少的任何字节已经被读取(我认为复制是唯一的方法来做到这一点)。以这种方式移除的字节数也将被保存。

我需要知道从原始开始的文件的当前位置与另一个文件进行同步。这应该很容易,因为它只是(current_offset + deleted_bytes)。

不容易的原因是fseek只使用长整型索引,它将文件限制为2GB,fsetpos使用位置索引的fpos_t结构,该结构不是数字,也不能来回转换到一个。我不知道有什么方法使用长整型索引来定位文件,这将是理想的解决方案。

我该怎么办?

+2

哪个平台? 'ftello()'和'fseeko()'可能是一个选项。 – 2012-01-16 02:51:14

+0

ftello和fseeko将符合POSIX.1标准,但> 2GB也是一个依赖于文件系统的问题。 – 2012-01-16 02:55:40

回答

6

在windows上,您可以使用_lseeki64()来执行64位查找。

为了与Linux兼容,你也可以在编译时增加-D_FILE_OFFSET_BITS=64,然后做你的一个标题:

#ifdef __MINGW32__ // or whatever you use to find out you're compiling on windows 
#define lseek _lseeki64 
#endif 

然后使用lseek()到处如常。这是可行的,因为windows忽略_FILE_OFFSET_BITS标志,linux不会看到lseek的重新定义。

还有_fseeki64()如果你喜欢FILE*版本,并有相当的64位tell()ftell()功能太(_telli64()_ftelli64())。

+0

我认为这就是我需要的。谢谢! – user1151125 2012-01-16 04:20:23

+0

不客气。关于使它可移植的另一个注意事项 - 我不记得windows是否声明'off_t',所以你可能还需要'#define off_t __int64'在窗口上(所以你可以写代码到[lseek()'接口](http ://www.kernel.org/doc/man-pages/online/pages/man2/lseek.2.html))。但我不是100%肯定 - 也许'off_t'现在定义在某处。 – 2012-01-16 04:31:15

+0

@TimothyJones如何在Windows中设置_file_offset_bits?我正在使用32位Windows7机器上的Visual Studio 2008进行编译。我试图按照这个例子http://coding.derkeiler.com/Archive/C_CPP/comp.lang.c/2006-12/msg03560。HTML,但我得到以下错误c2371:'off_t':重新定义;不同的基本类型 – savi 2015-02-25 20:14:24

1

添加编译标志-D_FILE_OFFSET_BITS=64,这使得fopenfseekoff_t等成为64位和可用于大于2 GB的大小更大的文件的操作。有关更多信息,请参阅Large File Support in Linux

+0

优秀的解决方案。不幸的是我应该提到我正在使用Windows和Visual Studio。 – user1151125 2012-01-16 03:33:45

+0

我想我没有想到编译器的具体解决方案。我搜索了Visual Studio文档,发现在Windows中使用64位索引的SetFilePointer。我希望能够让我的代码更加便携。也许我需要学习如何使用#ifdef来检测它在哪个平台上,并有一个编译器指令或其他东西的完整列表。 – user1151125 2012-01-16 03:43:25

+0

如果对Linux/OS X用户有用,我会留下答案。 Makefile将允许您通过平台确定编译选项。 – 2012-01-16 05:52:05