On windows _fseeki64 does not seek to SEEK_END cor

2019-02-15 16:06发布

问题:

I have reduced the problem to the following basic function which should simply print the number of bytes in the file.

When I execute it for a file of 83886080 bytes (80 MB) it prints the correct number. However for a file of 4815060992 bytes (4.48 GB) it prints 520093696 which is way to low.

It seems to have something to do with the SEEK_END option because if I set the pointer to 4815060992 bytes manually (e.g. _fseeki64(fp, (__int64)4815060992, SEEK_SET) _ftelli64 does return the correct position. So a workaround would be to get the proper file size without using SEEK_END, how is this done?

The code is compiled on a 32 bit Windows system (hence __int64, _iseeki64 and _ftelli64) with MinGW.

In short: what am I doing wrong here?

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);
}

回答1:

In Windows, you should be able to "go native" and just use GetFileSizeEx().

I would also advise you to read the generated code to see if it maybe is some 64-bit confusion that prevents your stdio-based code from working.



回答2:

sorry for not posting sooner but I have been preoccupied with other projects for a while. The following solution works:

__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);
}

The trick was using _open instead of fopen to open the file. I still don't understand exactly why this has to be done, but at least this works now. Thanks to everyone for your suggestions which eventually pointed me in the right direction. (this is a copy of the answer to related question number 4003405).