我试图得到一个大文件(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; }
还有其他的API调用会返回你的文件大小,而不会强制你创建一个文件句柄,特别是GetFileAttributesEx
。 但是,这个功能只是在幕后打开文件是完全合理的。
__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会更快。 他们可能是,但直到你有时间,你才会知道。
我也担心为了打开文件而付出的代价,只是为了得到它的大小而关闭它。 并决定询问演出柜台 ,看看这些演出真的有多贵。
这是用三种方法在同一文件上执行1个文件大小查询所花费的周期数。 测试2个文件:150 MB和1.5 GB。 有+/- 10%的波动,所以他们似乎不受实际文件大小的影响。 (显然这取决于CPU,但它给你一个很好的观点)
CreateFile
, GetFileSizeEx
, CloseHandle
GetFileAttributesEx
FindFirstFile
, FindClose
使用 ^ 的代码GIST 可以在这里找到 。
正如我们从这个非常科学的测试中可以看到的,slowest实际上是文件的开瓶器。 第二最慢是文件查找器,而赢家是属性读取器。 现在,就可靠性而言, CreateFile
应该比其他2更CreateFile
。但是我仍然不喜欢打开文件的概念来阅读它的大小…除非我在做大小关键的东西,否则我会去为属性 。
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; }
GetFileSize函数呢?
从C ++ 17开始, file_size就是标准库的一部分。 (然后执行者决定如何有效地做到这一点!)