在C语言中访问大文件

5
我需要使用C语言访问一个大于2GB的文件。程序每次运行时会从文件中读取可变数量的字节,并保存下一位置的信息。下一次运行程序时,将读取文件位置并从该位置开始读取一定数量的字节。
问题在于,有时候文件可能会被“压缩”,即将其复制到一个新文件中,减去已经读取的任何字节(我认为只有复制才能做到这一点)。以这种方式删除的字节数也将被保存。
我需要知道文件当前位置距离原始起点的距离,以便与另一个文件同步。这应该很容易,因为它只是(当前偏移量+删除的字节数)。
问题在于fseek只使用长整型索引,限制文件大小为2GB,而fsetpos使用fpos_t结构作为位置索引,它不是数字,不能相互转换。我不知道如何使用long long int索引进行文件定位,这将是理想的解决方案。
我该怎么办?

2
哪个平台?ftello()fseeko()可能是一个选项。 - Jonathan Leffler
ftello和fseeko将符合POSIX.1标准,但> 2GB也是文件系统相关问题。 - Ahmed Masud
2个回答

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的重新定义。
如果您喜欢FILE*版本,则还有_fseeki64(),并且还有相应的64位tell()ftell()函数(_telli64()_ftelli64())。

不用谢。关于可移植性的另一个注意事项 - 我不记得 Windows 是否声明了 off_t,所以在 Windows 上你可能还需要 #define off_t __int64 (这样你就可以编写代码来使用 lseek() 接口)。但我并不100%确定 - 或许现在已经定义了 off_t - Timothy Jones
@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
在Windows上,_FILE_OFFSET_BITS没有等效项。您需要使用您想要的64位版本函数。我相信off_t在Windows上是一个长整型(即仅32位)。您看到错误是因为该代码尝试重新定义off_t。您可以通过我的上面的评论中的建议解决此问题- #define off_t __int64(当然,仅适用于Windows)。 - Timothy Jones

1
添加编译标志-D_FILE_OFFSET_BITS=64,使得fopenfseekoff_t等变为64位,可用于操作大于2GB的文件。更多信息请参见Linux中的大文件支持

优秀的解决方案。不幸的是,我应该提到我正在使用Windows和Visual Studio。 - user1151125
我想我没有考虑过编译器特定的解决方案。我搜索了Visual Studio文档,并找到了在Windows中使用64位索引的SetFilePointer。虽然如此,我希望使我的代码更加可移植。也许我需要学习如何使用#ifdef来检测它所在的平台,并拥有一整套的编译器指令或其他东西。 - user1151125
我会留下答案,以防对Linux/OS X用户有用。Makefile将允许您通过平台确定编译选项。 - Alex Reynolds

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接