2010-10-23 159 views
4

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

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

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

nsamples的返回类型是一个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使用以下替换NSAMPLES:

__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字节我得到样本文件(例如_ftelli64给出字节)这很奇怪。

奇怪的是,当我离开(__int64)转换为_fseeki64时,我得到一个运行时错误(无效参数)。

任何想法?

+0

是Win32 API的一个选项吗? – 2010-10-23 10:01:29

+0

你使用什么编译器? GCC?视觉(东西)?还有别的吗? – 2010-10-26 00:01:01

+0

我正在使用MinGW(“不能”使用VS,因为我正在编写的函数是f2py Python扩展模块的一部分)。 Win32 API可能是一个选项,如果它可以很容易地集成到这个函数中而不会增加许多依赖(你可能会告诉我对Windows不熟悉)) – 2010-10-27 14:19:48

回答

2

抱歉没有更快发布,但我一直专注于其他项目一段时间。 下面的解决方案的工作原理:

__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打开该文件。 我仍然不明白为什么要这样做,但至少现在这个工作。 感谢大家的建议,最终指引我朝着正确的方向发展。

3

有两个函数调用_ fseeki64和_ ftelli64支持,即使在32位Windows较长文件偏移:

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

__int64 _ftelli64(FILE *stream); 
+0

我试过这个,但它似乎没有返回正确的值(请参见发布) – 2010-10-25 12:33:33

+0

你使用什么编译器?视觉工作室?什么版本? – Codo 2010-10-25 14:47:10

+0

我使用MinGW的最新版本(基本上GCC 4.5)。由于我正在编译的软件包是一个带有f2py的Python扩展,我不知道如何使用VisualStudio编译它。 – 2010-10-25 16:57:42

1

而对于GCC,看到这么质疑1035657。如果建议是用-D_FILE_OFFSET_BITS = 64标志编译的,那么f-move-around函数使用的隐藏变量(类型为off_t)就是64位。对于MinGW:“大文件支持(LFS)已经通过重新定义stat并寻找函数和类型到它们的64位等价物来实现。对于fseek和ftell,单独的LFS版本fseeko和ftello基于fsetpos和fgetpos,在LibGw32C中提供。“ (reference)。在最近的gcc版本中,fseeko和ftello是内置的,不需要单独的库。

+0

我认为这只适用于POSIX平台上的GCC吗? – 2010-10-25 14:26:12

+0

@Pim Schellart:我既不能确认也不否认。我目前使用的两个gcc设置是Linux/POSIX(在您的问题的上下文中)。在这些测试中,我看到了fseek()和ftell()的LFS行为。所以我无法在非POSIX环境中使用gcc进行测试。 – 2010-10-26 00:45:17

+0

fseeko和ftello提供最新的MinGW gcc 4.8.2;你不需要LibGw32C。 – JPaget 2014-02-06 01:47:05

1

我BC说:

520093696 + 4294967296 => 4815060992

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