2010-10-23 118 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位。返回的偏移量很可能是正確的,但會被切斷。