私は大きなファイル(12gb +)のファイルサイズを取得しようとしていますが、これを行うためにファイルを開きたくありません。それを行うための良いAPIはありますか?私はWindows環境にいます。
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の方が高速であると想定しないでください。彼らはそうかもしれないが、時間を計るまであなたは知らないだろう。
また、ファイルを開いてサイズを取得するためだけにファイルを閉じるために支払われる価格を恐れて生きてきました。パフォーマンスカウンター^ .
これは、3つの方法で同じファイルに対して1つのファイルサイズのクエリを実行するのにかかったサイクル数です。2つのファイルでテスト:150 MBおよび1.5 GB。 +/- 10%の変動があるため、実際のファイルサイズの影響を受けないようです。 (明らかにこれはCPUに依存しますが、それはあなたに良い視点を与えます)
CreateFile
、GetFileSizeEx
、CloseHandle
GetFileAttributesEx
FindFirstFile
、FindClose
使用されたコードの要点^はこちらから入手できます。
これからわかるように高度に科学的:) test、実際に最も遅いのはファイルオープナーです。 2番目に遅いのはファイルファインダーで、勝者は属性リーダーです。 今、信頼性の観点から、CreateFile
は他の2.よりも優先されるべきです。しかし、私はまだオープンのコンセプトが好きではありませんサイズを読み取るためだけのファイルです。サイズが重要な場合を除き、Attributesを使用します。
[〜#〜] ps [〜#〜]:時間があれば、サイズを読み取ろうとする開かれ、書き込み中のファイルの数。しかし、今は...
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;
}
C++ 17の時点では、標準ライブラリの一部として file_size があります。 (実装者は、それを効率的に行う方法を決定することができます!)
GetFileSize 関数はどうですか?