32-битные окна и ограничение размера файла 2 ГБ (C с FSEEK и FTELL)

StackOverflow https://stackoverflow.com/questions/4003405

Вопрос

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

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

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

Крайне важно, чтобы возвратный тип симпры представляет собой 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 Байты я получил 260046848 Образцы (например, _ftelli64 дает 520093696 байты) что странно.

Любопытно, когда я оставляю (__int64) вызов _fseeki64 Я получаю ошибку выполнения (неверный аргумент).

Есть идеи?

Это было полезно?

Решение 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 Чтобы открыть файл. Я до сих пор не понимаю точно, почему это должно быть сделано, но, по крайней мере, это работает сейчас. Спасибо всем за ваши предложения, которые в конечном итоге указали мне в правильном направлении.

Другие советы

Есть две функции, называемые _fseeki64. а также _ftelli64. Это поддерживает более длинные файловые смещения даже на 32-битных Windows:

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

__int64 _ftelli64(FILE *stream);

Мой до н.э. говорит:

520093696 + 4294967296 => 4815060992

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

И для GCC, см. Так вопрос 1035657. Отказ Там, где совет комбинируется с флагом -d_file_offset_bits = 64, так что скрытая переменная (ы) (типа OFF_T), используемая функциями F-перемещения, представляет собой (°) 64-бит.

Для MINGW: «Большой файловой поддержка (LFS) была реализована путем переопределения стандарта и искать функции и типы к своим эквивалентом 64-бит. Для Feek и Ftell отдельных версий LFS, FSEEKO и FTELLO на основе FSTPOS и FGEPPS, являются предоставленно Libgw32c.." (ссылка). В последние версии GCC, Fseeko и Ftello встроены, и отдельная библиотека не нужна.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top