在C + MinGW32中使用64位地址进行文件操作

9

我正在尝试用C语言读取一个24GB的XML文件,但是无法成功。我使用ftell()函数打印出当前位置,在读取过程中,一旦到达足够大的数字,它就会返回到较小的数字并重新开始,甚至没有读取文件的20%。我猜测这是由于存储位置的变量范围(long)的问题,根据http://msdn.microsoft.com/en-us/library/s3f49ktz(VS.80).aspx,它可以达到约40亿,而我的文件大小为250亿字节。long long应该可以解决问题,但我该如何更改编译器(Cygwin/mingw32)使用或让它支持fopen64?


8
哇,一个24GB的XML文件。 - Malfist
它的维基百科(整个内容) - zacaj
8
如果你成功读取了那个文件,你可以说:“我已经阅读完整个维基百科。” - Rubens Farias
1
你看过这个吗:http://arstechnica.com/gadgets/news/2009/10/openmoko-offline-reader-puts-wikipedia-in-your-pocket.ars - mocj
我不是 C 程序员,但你不能使用内存映射文件吗? - RCIX
显示剩余12条评论
6个回答

3

ftell()函数通常返回一个unsigned long,在32位系统上最多只能到2的32次方字节(4 GB)。因此,您无法将24 GB文件的文件偏移量适合32位long

您可能已经有ftell64()函数可用,或者标准的fgetpos()函数可以为您返回更大的偏移量。


我没有ftell64(),而fgetpos()返回与ftell()相同的内容。 - zacaj

3

2
不要吓唬人,那些是C函数和Windows API的一部分 :) - Dolphin

0

除非您可以像Loadmaster建议的那样使用64位方法,否则我认为您将不得不将文件分割。

此资源似乎表明可以使用_telli64()。但是我无法测试,因为我不使用mingw。


但是没有编译器选项或其他任何东西来启用它们?我可以在包含文件中看到它们,但它们被放在#ifdef下面。 - zacaj

0

我不知道有什么方法可以在一个文件中完成这个任务,如果适当地分割文件不是一个真正的选项,那么你可以编写一些函数来临时分割文件。其中一个函数使用ftell()在文件中移动并在达到分割点时将ftell()切换到新文件,然后另一个函数在退出之前将文件拼接在一起。这是一种非常糟糕的方法,但如果没有更好的解决方案出现,这可能是完成工作的一种方式。


0

我找到了答案。不再使用fopen,fseek,fread,fwrite...而是使用_open,lseeki64,read,write。现在我可以写入和查找大于4GB的文件。

编辑:似乎后面的函数比前面的函数慢了6倍。我会给予赏金给任何能解释这个问题的人。

编辑:哦,我在这里学到了read()和friends是未缓存的。 read()和fread()之间有什么区别?


-1

即使Microsoft C库中的ftell()返回32位值,因此一旦达到2 GB就会返回虚假值,但仅读取文件仍应正常工作。或者您也需要在文件中进行查找吗?对于这个问题,您需要使用_ftelli64()和_fseeki64()。

请注意,与某些Unix系统不同,您无需在打开文件时使用任何特殊标志来指示它处于某种“64位模式”。底层的Win32 API可以很好地处理大文件。


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