1. 程式人生 > >Windows開發--獲取檔案大小及獲取資料夾大小的方法

Windows開發--獲取檔案大小及獲取資料夾大小的方法

獲取檔案大小

Windows提供了好幾個API函式來獲取檔案大小,還可以使用標準C和標準C++庫函式來獲取(當然了,標準庫函式的底層實現也是呼叫了Windows API函式,效率上可能有所影響)。

const wchar_t* pFile = L"C:\\chromium.tar";//檔案大小9,332,330,496 位元組 32位整形無法裝下
HANDLE hFile = CreateFile(pFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (INVALID_HANDLE_VALUE != hFile)
{
	//方法一,使用Windows API GetFileSizeEx
	LARGE_INTEGER size;
	::GetFileSizeEx(hFile, &size);
	__int64 nSize1 = size.QuadPart;

	//方法二,使用Windows API GetFileSize
	DWORD dwHigh = 0;
	DWORD dwSize = ::GetFileSize(hFile, &dwHigh);
	__int64 nSize2 = ((__int64)dwHigh << 32) + dwSize;//對於大檔案需要將高32位和低32位拼接成64位整形
	CloseHandle(hFile);

	//方法三,使用Windows API GetFileAttributesEx
	WIN32_FILE_ATTRIBUTE_DATA fileAttr;
	GetFileAttributesEx(pFile, GetFileExInfoStandard, &fileAttr);
	__int64 nSize3 = ((__int64)fileAttr.nFileSizeHigh << 32) + fileAttr.nFileSizeLow;

	//確定三種發發讀取的檔案大小一致
	assert(nSize1 == nSize2 && nSize2 == nSize3);
}

//方法四,使用標準C庫函式實現
FILE* fp = NULL;
_wfopen_s(&fp, pFile, L"r");
if (fp)
{
	_fseeki64(fp, 0, SEEK_END);	//移動指標到檔案末尾
	__int64 nSize4 = _ftelli64(fp);//獲取檔案大小。不要使用ftell,檔案太大時32位整形會被截斷
	_fseeki64(fp, 0, SEEK_SET); //移動檔案指標到原來的位置(復原)
	//.........do something
	fclose(fp);
}

//方法五,使用標準C++庫函式實現
fstream ffile;
ffile.open(pFile, ios::in | ios::binary | ios::_Nocreate);
if (ffile.is_open())
{
	ffile.seekg(0, ffile.end);
	__int64 fileSize = ffile.tellg();
	ffile.close();
}

獲取資料夾大小

通過遍歷資料夾下面的檔案,累加計算最後的總大小。

__int64 GetFolderSize(const wstring& strDir)
{
	__int64 nSize = 0;
	wstring strRootPath = strDir + L"\\";
	wstring strRoot = strRootPath + L"*.*";
	WIN32_FIND_DATA fd;
	HANDLE hFind = FindFirstFile(strRoot.c_str(), &fd);
	if (INVALID_HANDLE_VALUE == hFind)
		return nSize;
	while (FindNextFile(hFind, &fd))
	{
		if (wcscmp(fd.cFileName, L".") == 0 || wcscmp(fd.cFileName, L"..") == 0)
			continue;
		wstring strPath = strRootPath + fd.cFileName;
		if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
			nSize += GetFolderSize(strPath);
		else
		{
			HANDLE hFile = CreateFile(strPath.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
			if (INVALID_HANDLE_VALUE == hFile)
				continue;
			LARGE_INTEGER size;
			if (::GetFileSizeEx(hFile, &size))
			{
				nSize += size.QuadPart;
			}
			CloseHandle(hFile);
		}
	}
	FindClose(hFind);
	return nSize;
}