写一个工具正好需要用到获取文件在磁盘上占用空间的大小,先普及一下知识吧
首先说一下“文件大小”和“占用空间”的区别,文件大小是指文件自身的大小,不管这个文件放在哪里大小都不会发生改变,而占用空间是指文件所在分区占用的空间,文件放在不同的分区所占用的空间可能会有所不同,占用空间一般大于等于文件大小。这里我们先做个实验,
在cmd里输入如下代码
fsutil file createnew F:\TestFile.dat 12345678
此时在F盘下创建了一个TestFile.dat的文件,然后把该文件复制到另外一个盘,文件大小和占用空间如图所示:
可以看出。两个一样的文件,在不同分区下。出现了占用空间大小不相同,这涉及到了磁盘文件的存储机制,下面解释下原因。
磁盘文件大小以字节(Byte)为单位,在文件不发生改变的情况下,大小不变,而文件在磁盘上占用的空间,是以簇(Cluster)为单位,2^n个扇区组成一个簇,一个簇只能放一个文件,所以文件的占用空间需要对齐到簇大小的整数倍,如果文件大小刚好是簇的倍数。那么文件大小和占用空间是一致的,磁盘分区格式和容量大小决定了簇的大小。所以可能出现文件在不同分区的占用空间大小不一样。在cmd下可以利用chkdsk命令来查看一个分区的簇大小,例如我这里查看F盘的结果:
这里所看到的分配单元就是簇大小,4096byte。
要计算某个文件占用空间的大小,可以使用如下的公式
簇数 = 向上取整(文件大小/簇大小)
占用空间 = 簇数 * 簇大小
获取簇的大小可以使用GetDiskFreeSpace这个API来获取每簇的扇区数和每扇区的字节数。然后相乘即可得到簇大小。
详细代码如下:
// GetFileSpaceSize.cpp : Defines the entry point for the console application.
//
/************************************************************************
* author: HwangBae
* created: 2012/07/21
* Blog: http://hwangbae.cnblogs.com/
* Email: hwangbae@live.cn
************************************************************************/
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <math.h>
int _tmain(int argc, _TCHAR* argv[])
{
if (argc < 2)
{
_tprintf_s(_T("Usage: GetFileSpaceSize filename\n"));
return -1;
}
// 文件路径
LPCTSTR szFileName = argv[1];
// 打开文件句柄
HANDLE hFile = ::CreateFile(szFileName, GENERIC_READ | FILE_SHARE_READ, 0,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
_tprintf_s(_T("Failed to create file handle: %s ! error code:%d\n"), szFileName, GetLastError());
return -1;
}
// 获取文件大小
UINT64 uFileSize = 0;
::GetFileSizeEx(hFile, (PLARGE_INTEGER)&uFileSize);
::CloseHandle(hFile);
// 获取磁盘根路径
TCHAR szVolumePathName[] = _T("C:\\");
::GetVolumePathName(szFileName, szVolumePathName, sizeof(szVolumePathName) / sizeof(TCHAR));
// 保存簇信息的变量
DWORD dwSectorsPerCluster = 0;
DWORD dwBytesPerSector = 0;
DWORD dwNumberOfFreeClusters = 0;
DWORD dwTotalNumberOfClusters = 0;
// 获取簇信息
if (!::GetDiskFreeSpace(
szVolumePathName, //磁盘根路径
&dwSectorsPerCluster, //每簇的扇区数
&dwBytesPerSector, //每扇区的字节数
&dwNumberOfFreeClusters, //空余簇的数量
&dwTotalNumberOfClusters //全部簇的数量
)
)
{
_tprintf_s(_T("Failed to get disk cluster info! error code: %d\n"), GetLastError());
return -1;
}
// 簇大小 = 每簇的扇区数 * 每扇区的字节数
DWORD dwClusterSize = dwSectorsPerCluster * dwBytesPerSector;
// 计算文件占用空间
// 公式:(以字节为单位)
// 簇数 = 向上取整(文件大小 / 簇大小)
// 占用空间 = 簇数 * 簇大小
UINT64 dwFileSpacesize = (UINT64)(ceil(uFileSize / (double)dwClusterSize) * dwClusterSize);
_tprintf_s(_T("FileName : %s\n"), szFileName);
_tprintf_s(_T("FileSize : %I64u Byte\n"), uFileSize);
_tprintf_s(_T("FileSpacesSize : %I64u Byte\n"), dwFileSpacesize);
return 0;
}
方法二:
// GetFileSpaceSize.cpp : Defines the entry point for the console application.
//
/************************************************************************
* author: HwangBae
* created: 2012/07/23
* Blog: http://hwangbae.cnblogs.com/
* Email: hwangbae@live.cn
************************************************************************/
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#define CLOSE_HANDLE(x) {CloseHandle(x); x = NULL;}
int _tmain(int argc, _TCHAR* argv[])
{
if (argc < 2)
{
_tprintf_s(_T("Usage: GetFileSpaceSize filename\n"));
return -1;
}
// 文件路径
LPCTSTR szFileName = //argv[1];
// 打开文件句柄
HANDLE hFile = ::CreateFile(szFileName, GENERIC_READ | FILE_SHARE_READ, 0,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
_tprintf_s(_T("Failed to create file handle: %s ! error code:%d\n"), szFileName, GetLastError());
return -1;
}
// 获取文件大小
UINT64 uFileSize = 0;
::GetFileSizeEx(hFile, (PLARGE_INTEGER)&uFileSize);
FILE_STANDARD_INFO fsi = {0};
if (!::GetFileInformationByHandleEx(hFile, FileStandardInfo, &fsi, sizeof(FILE_STANDARD_INFO)))
{
_tprintf_s(_T("Failed to get file info! error code:%d\n"), GetLastError());
CLOSE_HANDLE(hFile);
return -1;
}
_tprintf_s(_T("FileName : %s\n"), szFileName);
_tprintf_s(_T("FileSize : %I64u Byte\n"), uFileSize);
_tprintf_s(_T("FileSpacesSize : %I64u Byte\n"), fsi.AllocationSize);
CLOSE_HANDLE(hFile);
return 0;
}
测试结果:
欢迎转载本文章,但请标明出处,原文地址:
http://www.cnblogs.com/hwangbae/archive/2012/07/21/2602592.html如果觉得本文对您有帮助,请支持一下,您的支持是我写作最大的动力,谢谢。
分享到:
相关推荐
VC++用于获取文件大小的四种方法,很齐全哟~
VC++实现PE文件分析工具
VC++图像操作实例,获取BMP图像的尺寸大小,注意这里不是获取的占用字节,是像素,你随便载入一个BMP位图,点击“获取大斜按钮,BMP的长度和宽度会显示出来,这是个很简单的图像基础操作,新手朋友应该掌握的哦。
VC++实现xml文件操作,自己在网上找的一些资料。
VC++ 实现增大可执行文件的体积 自定义文件大小
VC++ 获得文件属性 获取文件的创建时间、修改时间、访问时间以及是否是只读、存档、隐藏、系统等属性。
VC++帮助文件VC++帮助文件VC++帮助文件VC++帮助文件
基于VC++实现WAV文件播放器,供编程人员使用
用VC++语言编程,实现了wav文件路径的打开和音频的播放
VC++逐行读取文本文件,VC++逐行读取文本文件,VC++逐行读取文本文件,
VC++源码,可以获取当前用户及所有用户桌面上的文件及快捷方式列表
VC++实现 使用SOCKET编程中select模型实现文件下载
vc++6.0实现文件下载器
用vc++在http协议下实现文件的上传和下载 里面包含的几个文档可供大家研究
VC++实现文件下载功能!程序源代码一见就懂,很简单啊。
VC++实现两台电脑文件传输,网络传输支持。
VC++ 文件的删除 文件操作 欢迎下载
VC++ 实现简单的文件加密与解密功能 很实用,可以参考参考。
首先系统介绍了avi格式,然后详细介绍了怎么样用VC++实现avi文件的合成与分解
Windows运行库VC++离线安装文件。Windows运行库VC++离线安装文件。Windows运行库VC++离线安装文件。