На Windows _fseeki64 не пытается SEEK_END правильно для больших файлов - PullRequest
2 голосов
/ 27 октября 2010

Я сократил проблему до следующей базовой функции, которая должна просто напечатать число байтов в файле.

Когда я выполняю его для файла 83886080 байтов (80 МБ), он печатает правильное число,Однако для файла размером 4815060992 байта (4,48 ГБ) он печатает 520093696, что является слишком низким значением.

Кажется, что-то связано с параметром SEEK_END , потому что если я установлю указатель на4815060992 байта вручную (например, _fseeki64(fp, (__int64)4815060992, SEEK_SET) _ftelli64 возвращает правильную позицию. Таким образом, обходной путь может быть для получения правильного размера файла без использования SEEK_END , как это сделать?

код скомпилирован в 32-битной системе Windows (отсюда __int64, _iseeki64 и _ftelli64) с MinGW.

Короче: что я здесь не так делаю?

void printbytes(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 bytes */
  n = _ftelli64(fp);

  printf("%I64d\n", n);

  /* Close file */
  fclose(fp);
}

Ответы [ 2 ]

1 голос
/ 15 февраля 2011

извините за то, что не публиковал сообщения раньше, но некоторое время я был занят другими проектами.Работает следующее решение:

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

1 голос
/ 27 октября 2010

В Windows вы должны быть в состоянии "перейти на родную" и просто использовать <a href="http://msdn.microsoft.com/en-us/library/aa364957%28v=VS.85%29.aspx" rel="nofollow">GetFileSizeEx()</a>.

Я бы также посоветовал вам прочитать сгенерированный код, чтобы увидеть, не является ли это какой-то 64-битной путаницейпредотвращает работу вашего кода на основе stdio.

...