2010-10-23 7 views
4

Я пытаюсь перенести небольшую программу анализа данных из 64-разрядной UNIX в 32-разрядную систему Windows XP (не спрашивайте :)). Но теперь у меня проблемы с ограничением размера файла 2 ГБ (длинный не 64 бит на этой платформе).32-разрядная версия Windows и ограничение размера файла 2GB (C с fseek и ftell)

Я искал этот сайт и другие возможности для возможных решений, но не могу найти то, что напрямую можно перевести на мою проблему. Проблема заключается в использовании fseek и ftell.

Кто-нибудь знает о модификации следующих двух функций, чтобы заставить их работать с 32-разрядной Windows XP для файлов размером более 2 ГБ (на самом деле порядка 100 ГБ).

Жизненно важно, чтобы возвращаемый тип 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

Какой компилятор вы используете? НКУ? Визуальный (что-то)? Что-то другое? –

+0

Я использую MinGW («не могу» использовать VS, поскольку функции, которые я пишу, являются частью модуля расширения f2py Python). Win32 API может быть вариантом, если его можно легко интегрировать в эту функцию, не добавляя к многим зависимостям (как вы, вероятно, можете сказать, что я не знаком с Windows :)) –

ответ

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

Я пробовал это, но он, похоже, не возвращает правильные значения (см. Сообщение) –

+0

Какой компилятор вы используете? VisualStudio? И какая версия? – Codo

+0

Я использую последнюю версию MinGW (в основном GCC 4.5). Поскольку пакет, который я компилирую, является расширением Python с f2py, и я не знаю, как скомпилировать его с помощью VisualStudio. –

1

И для НКУ, см так вопрос 1035657. Где совет компилируется с флагом -D_FILE_OFFSET_BITS = 64, так что скрытые переменные (типа off_t), используемые функциями f-move-around, являются 64-битными.

Для MinGW: «Поддержка больших файлов (LFS) реализована путем переопределения статусов и поиска функций и типов для их 64-разрядных эквивалентов. Для fseek и ftell отдельные версии LFS, fseeko и ftello, основанные на fsetpos и fgetpos, приведены в LibGw32C. " (reference). В последних версиях gcc, fseeko и ftello встроены, и отдельная библиотека не нужна.

+0

Я думаю, что работает только на GCC на платформе POSIX? –

+0

@Pim Schellart: Я не могу ни подтвердить, ни опровергнуть это. Мои две действующие gcc-установки - это Linux/POSIX (в контексте вашего вопроса). Тестирование на них, я вижу поведение LFS из fseek() и ftell(). Поэтому я не могу протестировать gcc в среде, отличной от POSIX. –

+0

fseeko и ftello представлены последние версии MinGW gcc 4.8.2; вам не нужен LibGw32C. – JPaget

1

Мой БК говорит:

520093696 + 4294967296 => 4815060992

Я предполагаю, что ваша процедура печати 32-бит. Ваше смещение вернулось, скорее всего, правильно, но где-то его отрубили.