Windows では、_fseek64 が大きなファイルに対して正しく SEEK_END をシークしません

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

質問

問題を次の基本関数に減らしました。これにより、ファイル内のバイト数を単純に印刷する必要があります。

83886080 バイト (80 MB) のファイルに対して実行すると、正しい数値が出力されます。ただし、4815060992 バイト (4.48 GB) のファイルの場合、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

すぐに投稿できなくて申し訳ありませんが、しばらく他のプロジェクトに夢中になっていました。次の解決策は機能します。

__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 に対する回答のコピーです)。

他のヒント

Windows では、「ネイティブに移行」して単に使用できるはずです。 GetFileSizeEx().

また、生成されたコードを読んで、stdio ベースのコードが機能しない原因となっている 64 ビットの混乱がないかどうかを確認することをお勧めします。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top