32位Windows和2GB文件大小限制(C与fseek和ftell)

我试图将一个小型的数据分析程序从一个64位的UNIX移植到一个32位的Windows XP系统(不要问:))。 但是现在我遇到了2GB文件大小限制的问题(在这个平台上不是64位)。

我已经search了这个网站和其他可能的解决scheme,但找不到任何可以直接翻译我的问题。 问题在于使用fseek和ftell。

有谁知道以下两个函数的修改,使他们在32位Windows XP上工作的文件大于2GB(实际订购100GB)。

nsamples的返回types是一个64位整数(可能是int64_t)是非常重要的。

long nsamples(char* filename) { FILE *fp; long n; /* Open file */ fp = fopen(filename, "rb"); /* Find end of file */ fseek(fp, 0L, SEEK_END); /* Get number of samples */ n = ftell(fp) / sizeof(short); /* Close file */ fclose(fp); /* Return number of samples in file */ return n; } 

 void readdata(char* filename, short* data, long start, int n) { FILE *fp; /* Open file */ fp = fopen(filename, "rb"); /* Skip to correct position */ fseek(fp, start * sizeof(short), SEEK_SET); /* Read data */ fread(data, sizeof(short), n, fp); /* Close file */ fclose(fp); } 

我尝试使用_fseeki64和_ftelli64来replacensamples:

 __int64 nsamples(char* filename) { FILE *fp; __int64 n; int result; /* Open file */ fp = fopen(filename, "rb"); if (fp == NULL) { perror("Error: could not open file!\n"); return -1; } /* Find end of file */ result = _fseeki64(fp, (__int64)0, SEEK_END); if (result) { perror("Error: fseek failed!\n"); return result; } /* Get number of samples */ n = _ftelli64(fp) / sizeof(short); printf("%I64d\n", n); /* Close file */ fclose(fp); /* Return number of samples in file */ return n; } 

对于4815060992个字节的文件,我得到260046848个样本(例如_ftelli64给出520093696个字节),这很奇怪。

奇怪的是,当我在_fseeki64调用中_fseeki64 (__int64) ,我得到一个运行时错误(无效的参数)。

有任何想法吗?

有两个函数称为_ fseeki64和_ ftelli64 ,即使在32位Windows上也支持更长的文件偏移量:

 int _fseeki64(FILE *stream, __int64 offset, int origin); __int64 _ftelli64(FILE *stream); 

对不起,不早发布,但我一直在其他项目一直专注于。 以下解决方案工作:

 __int64 nsamples(char* filename) { int fh; __int64 n; /* Open file */ fh = _open( filename, _O_BINARY ); /* Find end of file */ n = _lseeki64(fh, 0, SEEK_END); /* Close file */ _close(fh); return n / sizeof(short); } 

诀窍是使用_open而不是fopen来打开文件。 我仍然不明白为什么要这样做,但至少现在这个工作。 感谢大家的建议,最终指引我朝着正确的方向发展。

我的BC说:

520093696 + 4294967296 => 4815060992

我猜你的打印程序是32位的。 返回的偏移量很可能是正确的,但会被切断。

对于gcc,请参阅问题1035657 。 如果建议是用-D_FILE_OFFSET_BITS = 64标志编译的,那么f-move-around函数使用的隐藏变量(类型为off_t)就是64位。

对于MinGW:“大文件支持(Large-File Support,LFS)”是通过重新定义stat并寻找函数和类型为64位的等价方式来实现的。对于fseek和ftell,单独的LFS版本fseeko和ftello基于fsetpos和fgetpos在LibGw32C中提供。“ ( 参考 )。 在最近的gcc版本中,fseeko和ftello是内置的,不需要单独的库。