web-dev-qa-db-ja.com

C ++でファイルを開かずにファイルサイズを確認しますか?

私は大きなファイル(12gb +)のファイルサイズを取得しようとしていますが、これを行うためにファイルを開きたくありません。それを行うための良いAPIはありますか?私はWindows環境にいます。

28
user1167566

GetFileSizeEx を呼び出す必要があります。これは、古い GetFileSize よりも使いやすいです。 CreateFileを呼び出してファイルを開く必要がありますが、これは安価な操作です。ファイルを開くのは高価であり、12GBのファイルでも費用がかかるという仮定は誤りです。

次の関数を使用して、ジョブを完了できます。

__int64 FileSize(const wchar_t* name)
{
    HANDLE hFile = CreateFile(name, GENERIC_READ, 
        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 
        FILE_ATTRIBUTE_NORMAL, NULL);
    if (hFile==INVALID_HANDLE_VALUE)
        return -1; // error condition, could call GetLastError to find out more

    LARGE_INTEGER size;
    if (!GetFileSizeEx(hFile, &size))
    {
        CloseHandle(hFile);
        return -1; // error condition, could call GetLastError to find out more
    }

    CloseHandle(hFile);
    return size.QuadPart;
}

ファイルハンドル、特に GetFileAttributesEx を作成せずにファイルサイズを返すAPI呼び出しが他にもあります。ただし、この関数がバックグラウンドでファイルを開くだけであることは完全に妥当です。

__int64 FileSize(const wchar_t* name)
{
    WIN32_FILE_ATTRIBUTE_DATA fad;
    if (!GetFileAttributesEx(name, GetFileExInfoStandard, &fad))
        return -1; // error condition, could call GetLastError to find out more
    LARGE_INTEGER size;
    size.HighPart = fad.nFileSizeHigh;
    size.LowPart = fad.nFileSizeLow;
    return size.QuadPart;
}

Visual Studioでコンパイルしていて、Win32 APIの呼び出しを避けたい場合は、 _wstat64

がここにあります _wstat64ベースの関数のバージョン:

__int64 FileSize(const wchar_t* name)
{
    __stat64 buf;
    if (_wstat64(name, &buf) != 0)
        return -1; // error, could use errno to find out more

    return buf.st_size;
} 

パフォーマンスが問題になった場合は、意思決定に到達するために、ターゲットとするすべてのプラットフォームでさまざまなオプションを使用する必要があります。 CreateFileを呼び出す必要のないAPIの方が高速であると想定しないでください。彼らはそうかもしれないが、時間を計るまであなたは知らないだろう。

44
David Heffernan

また、ファイルを開いてサイズを取得するためだけにファイルを閉じるために支払われる価格を恐れて生きてきました。パフォーマンスカウンター^ .

これは、3つの方法で同じファイルに対して1つのファイルサイズのクエリを実行するのにかかったサイクル数です。2つのファイルでテスト:150 MBおよび1.5 GB。 +/- 10%の変動があるため、実際のファイルサイズの影響を受けないようです。 (明らかにこれはCPUに依存しますが、それはあなたに良い視点を与えます)

  • 190サイクル-CreateFileGetFileSizeExCloseHandle
  • 40サイクル-GetFileAttributesEx
  • 150サイクル-FindFirstFileFindClose

使用されたコードの要点^はこちらから入手できます

これからわか​​るように高度に科学的:) test、実際に最も遅いのはファイルオープナーです。 2番目に遅いのはファイルファインダーで、勝者は属性リーダーです。 今、信頼性の観点から、CreateFileは他の2.よりも優先されるべきです。しかし、私はまだオープンのコンセプトが好きではありませんサイズを読み取るためだけのファイルです。サイズが重要な場合を除き、Attributesを使用します。

[〜#〜] ps [〜#〜]時間があれば、サイズを読み取ろうとする開かれ、書き込み中のファイルの数。しかし、今は...

28
CodeAngry

FindFirstFile 関数を使用する別のオプション

#include "stdafx.h"
#include <windows.h>
#include <tchar.h>
#include <stdio.h>

int _tmain(int argc, _TCHAR* argv[])
{
   WIN32_FIND_DATA FindFileData;
   HANDLE hFind;
   LPCTSTR  lpFileName = L"C:\\Foo\\Bar.ext";

   hFind = FindFirstFile(lpFileName , &FindFileData);
   if (hFind == INVALID_HANDLE_VALUE) 
   {
      printf ("File not found (%d)\n", GetLastError());
      return -1;
   } 
   else 
   {
      ULONGLONG FileSize = FindFileData.nFileSizeHigh;
      FileSize <<= sizeof( FindFileData.nFileSizeHigh ) * 8; 
      FileSize |= FindFileData.nFileSizeLow;
      _tprintf (TEXT("file size is %u\n"), FileSize);
      FindClose(hFind);
   }
   return 0;

}
9
RRUZ

C++ 17の時点では、標準ライブラリの一部として file_size があります。 (実装者は、それを効率的に行う方法を決定することができます!)

2
Davis Herring

GetFileSize 関数はどうですか?

1
Armen Tsirunyan