当前位置: 首页 > article >正文

Windows程序设计8:获取文件大小的两种方式

文章目录

  • 前言
  • 一、GetFileSize获取文件大小
    • 1.小于4GB的文件
    • 2.大于4GB的文件
  • 二、GetFileSizeEx获取文件大小
  • 总结


前言

Windows程序设计8:获取文件大小的两种方式。


一、GetFileSize获取文件大小

该函数用于获取指定文件的大小(长度),以字节为单位,函数声明为

DWORD WINAPI GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh);

参数HANDLE hFile表示待获取大小的文件句柄,该文件句柄必须具有GENERIC_READ | GENERIC_WRITE访问权限,具体见CreateFile函数。
参数LPDWORD lpFileSizeHigh指向一个DWORD变量的指针,该变量用于接收文件大小高端(第32-64位)部分的值,如不需要获取这部分的值,该参数可以为NULL。

返回值:如果函数调用成功,返回值为文件大小低端(第0-31位)的值,如果参数LPDWORD lpFileSizeHigh不为NULL,该参数对应的变量包含文件大小高端(第32-64位)部分的值。
如果函数调用失败,且参数LPDWORD lpFileSizeHigh为NULL,返回值为INVALID_FILE_SIZE,可用GetLastError获取错误码。
如果函数调用失败,且参数LPDWORD lpFileSizeHigh不为NULL,返回值为INVALID_FILE_SIZE,可用GetLastError获取错误码,错误码为NO_ERROR之外的值。

这里对低端(第0-31位)和高端(第32-64位)进行说明:低端能够表示的最大文件大小为4GB,即对于二进制来说32位都为1时的最大字节数对应的GB大小。如果文件大小低于4GB,则只使用低端(第0-31位)即可,第二个参数设为NULL即可;超过4GB就需要用到高端(第32-64位),也就需要用到第二个参数。

1.小于4GB的文件

这里利用E盘下的111new.gif进行说明
在这里插入图片描述
程序代码如下

	// 打开E盘下的111new.gif并返回文件大小
	HANDLE handle2 = CreateFile(_T("E:\\111new.gif"), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	if (handle2 != INVALID_HANDLE_VALUE)
	{
		DWORD dw1 = GetFileSize(handle2, NULL);
		TCHAR sz1[128] = { 0 };
		_stprintf_s(sz1, 128, _T("文件大小为:%d"), dw1);
		MessageBox(NULL, sz1, _T("提示"), MB_OK);
		CloseHandle(handle2);
	}
	else
	{
		MessageBox(NULL, _T("文件打开失败"), _T("提示"), MB_OK);
	}

可以看到得到的文件大小和在属性中看到的一样。这里低版本的编译器还可以使用函数_stprintf,或者在高版本编译器中加入宏来禁止警告出现。因为函数_stprintf存在溢出风险,在高版本编译器中被认为是不安全的,相关问题大家可以自行查询,也比较简单。
在这里插入图片描述

2.大于4GB的文件

这里使用之前重装系统使用的Win10镜像文件进行说明,文件大小如下
在这里插入图片描述
代码中只需要将上述的文件路径进行更改即可,这里不再重复放置代码

运行后发现得到的结果与文件属性中查看到的文件大小是不一样的。造成这种现象的原因就是由于该文件大小超过了4GB
在这里插入图片描述
那么就需要借助GetFileSize函数的第二个参数
更改后的代码如下

	HANDLE handle2 = CreateFile(_T("D:\\技术支持\\ISO win10\\Win10_1803_China_GGK_Chinese(Simplified)_x64.iso"), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	if (handle2 != INVALID_HANDLE_VALUE)
	{
		DWORD dw_h = 0;//高32位
		DWORD dw1 = GetFileSize(handle2, &dw_h);
		LONGLONG Lw1= ((LONGLONG)dw_h << 32) | dw1;// 存储64位数字,将dw_h转化为64位并左移32位,再与dw1按位或
		TCHAR sz1[128] = { 0 };
		_stprintf_s(sz1, 128, _T("文件大小为:%lld"), Lw1);
		MessageBox(NULL, sz1, _T("提示"), MB_OK);
		CloseHandle(handle2);
	}
	else
	{
		MessageBox(NULL, _T("文件打开失败"), _T("提示"), MB_OK);
	}

得到的结果为
在这里插入图片描述
与在文件属性中查看到的一样。
当然,即便文件的大小小于4GB,也可以传入第二个参数,不影响结果,只不过第二个参数对应的高32位均为0。因此,推荐使用第二个参数,因为使用第二个参数后,既能获取小于4GB的文件大小,也能获取大于4GB的问加你大小。

二、GetFileSizeEx获取文件大小

该函数相对来说更方便一些,因为不涉及到低32位和高32位的整合问题。其函数原型为

BOOL GetFileSizeEx(
  HANDLE         hFile,          // 文件句柄
  PLARGE_INTEGER lpFileSize      // 指向 LARGE_INTEGER 结构的指针,用于接收文件大小
);

第一个参数HANDLE hFile为一个打开的文件句柄。
第二个参数PLARGE_INTEGER lpFileSize为LARGE_INTEGER类型的一个指针,LARGE_INTEGER 是一个联合体,用于表示 64 位整数。它的定义如下:

typedef union _LARGE_INTEGER {
  struct {
    DWORD LowPart;   // 低 32 位
    LONG  HighPart;  // 高 32 位
  };
  LONGLONG QuadPart; // 完整的 64 位值
} LARGE_INTEGER;

可以通过 QuadPart 直接访问 64 位值。
也可以通过 LowPart 和 HighPart 分别访问低 32 位和高 32 位。

返回值为布尔类型,执行成功返回TRUE,执行失败返回FALSE。

首先查看上述大于4GB的Win10镜像文件

HANDLE handle3 = CreateFile(_T("D:\\技术支持\\ISO win10\\Win10_1803_China_GGK_Chinese(Simplified)_x64.iso"), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	if (handle3 != INVALID_HANDLE_VALUE)
	{
		LARGE_INTEGER fz = {0};
		BOOL bret = GetFileSizeEx(handle3, &fz);
		if (bret) // 如果执行成功
		{
			TCHAR sz1[128] = { 0 };
			_stprintf_s(sz1, 128, _T("文件大小为:%lld"), fz.QuadPart);
			MessageBox(NULL, sz1, _T("提示"), MB_OK);
		}
		CloseHandle(handle3);
	}
	else
	{
		MessageBox(NULL, _T("文件打开失败"), _T("提示"), MB_OK);
	}

函数执行成功
在这里插入图片描述
然后查看上述小于4GB的gif文件,更换路径即可,同样执行成功
在这里插入图片描述
显然,GetFileSizeEx使用起来更方便一些,不用区分文件的大小直接使用即可,也不需要对高32位和低32位的数据进行人为拼接。


总结

Windows程序设计8:获取文件大小的两种方式。


http://www.kler.cn/a/526117.html

相关文章:

  • 【HarmonyOS之旅】基于ArkTS开发(三) -> 兼容JS的类Web开发(一)
  • Oracle Primavera P6 最新版 v24.12 更新 2/2
  • 数据结构 前缀中缀后缀
  • 毕业设计--具有车流量检测功能的智能交通灯设计
  • 【二叉树的深搜】二叉树剪枝
  • Ubuntu安装VMware17
  • C++ 堆栈分配的区别
  • 【Block总结】PConv,部分卷积|即插即用
  • 【数据结构】最有效的实现栈和队列的方式(CC++语言版)
  • 计算机组成原理学习笔记
  • 组合模式 - 组合模式的实现
  • 从0开始使用面对对象C语言搭建一个基于OLED的图形显示框架(OLED设备层封装)
  • Sqoop源码修改:增加落地HDFS文件数与MapTask数量一致性检查
  • [Java]泛型(二)泛型方法
  • AJAX综合案例——图书管理
  • 01-时间与管理
  • DeepSeek-R1 论文解读:强化学习如何 “炼” 出超强推理模型?
  • 使用 Context API 管理临时状态,避免 Redux/Zustand 的持久化陷阱
  • Web-3.0学习路线
  • Python学习之旅:进阶阶段(六)数据结构-有序字典(collections.OrderedDict)