ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

C++编程实践—C++处理磁盘大小

2026/8/7 1:48:40 拓冰建站 浏览量
C++编程实践—C++处理磁盘大小

一、磁盘容量监控

在实际的编程,经常会遇到对磁盘容量进行监控的情况。当磁盘的应用达到一个阀值时,就需要向用户发出报警信息,并针对具体的操作进行限制,以防止出现意外的事故。一般来说,对硬盘的处理,都是各个平台提供自己专属的API来保证对硬盘容量获取的准确性。但随着C++标准的演进,在C++17中也提供了相关的方法。
在前面的“Linux下获得磁盘和目录大小”中已经给出了一个完整的例子。本文将通过C++17标准中的方法与之对比,可以更好的理解相关的应用。

二、Linux下传统的方式

在Linux中,对硬盘的监控的方法有几种方法:

  1. 使用命令方式
    可以通过命令行或在C++中使用相关接口如system来实现命令的调用:
    iRet=popen(cmd.c_str()"r");fgets(buffer.data(),buffer.size(),pipe.get()
    buffer.data()中就是相关的内容
  2. 使用statvfs接口
    此函数是POSIX推荐的接口,头文件为 <sys/statvfs.h>,相对上层,应用方式如下:
    intret=statvfs(devInfo.mountPoint.c_str(),&fsStat);
  3. 使用statfs
    它需要包含#include <sys/vfs.h> 或 #include <sys/statfs.h>,是一个更底层的函数。应用如下:
    ret=statfs(path.c_str(),&s);

三、Windows下传统的方式

在Windows平台上,std::filesystem::space接口是使用GetDiskFreeSpaceExW接口来实现的。其定义如下:

BOOLGetDiskFreeSpaceEx(LPCWSTR lpRootPathName,// 根路径PULARGE_INTEGER lpFreeBytesAvailable,// 用户可用空间 : space_info.availablePULARGE_INTEGER lpTotalNumberOfBytes,// 总空间 :space_info.capacityPULARGE_INTEGER lpTotalNumberOfFreeBytes// 总空闲空间 : space_info.free);

四、c++17中的方法

在C++17后,标准库提供了库,其中的std::filesystem::space可以用来获取相关的磁盘的信息。其基本的定义如下:

structspace_info{std::uintmax_tcapacity;//文件系统的总大小,单位为字节std::uintmax_tfree;//可用空间,单位为字节std::uintmax_tavailable;//非特权进程可用的空闲空间,可能小于free};

在Linux上其具体的实现,其实就是调用statvfs接口。使用它需要注意以下几点:

  1. 权限,在Linux上很多情况下需要权限,否则可能无法成功读取相关的文件系统信息。此时要注意看返回的错误代码
  2. 不同分区处理,可能需要遍历所有的挂载点。这需要去读取/proc/mounts或/etc/mtab,然后再次调用相关接口即可
  3. 需要注意平台是32位还是64位。32位情况下可能对大磁盘(大于2T)的信息描述不对。因为使用字节描述,可能会溢出

五、例程

下面看传统的实现以及C++17的实现例程,Windows平台:

#include<windows.h>#include<iostream>#include<string>boolGetDiskSpaceInfo(conststd::wstring&path,unsignedlonglong&totalBytes,unsignedlonglong&freeBytes,unsignedlonglong&availableBytes){ULARGE_INTEGER totalAvailable;ULARGE_INTEGER totalBytes;ULARGE_INTEGER totalFreeBytes;BOOL ret=GetDiskFreeSpaceExW(path.c_str(),&totalAvailable,&totalBytes,&totalFreeBytes);if(!ret){returnfalse;}availableBytes=totalAvailable.QuadPart;totalBytes=totalBytes.QuadPart;freeBytes=totalFreeBytes.QuadPart;returntrue;}//GBstd::stringFormatBytes(unsignedlonglongbytes){constdoublegb=bytes/(1024.0*1024.0*1024.0);charbuf[64];snprintf(buf,sizeof(buf),"%.2f GB",gb);returnstd::string(buf);}intmain(){std::wstring path=L"C:\\";unsignedlonglongtotal,freeSpace,available;GetDiskSpaceInfo(path,total,freeSpace,available);return0;}

Linux中传统的应用可参看“Linux下获得磁盘和目录大小”的例程。下面看C++17实现(来自cppreference):

#include<cstdint>#include<filesystem>#include<iostream>#include<locale>std::uintmax_tdisk_usage_percent(conststd::filesystem::space_info&si,bool is_privileged=false)noexcept{if(constexpr std::uintmax_tX(-1);si.capacity==0||si.free==0||si.available==0||si.capacity==X||si.free==X||si.available==X)return100;std::uintmax_tunused_space=si.free,capacity=si.capacity;if(!is_privileged){conststd::uintmax_tprivileged_only_space=si.free-si.available;unused_space-=privileged_only_space;capacity-=privileged_only_space;}conststd::uintmax_tused_space{capacity-unused_space};return100*used_space/capacity;}voidprint_disk_space_info(autoconst&dirs,intwidth=14){(std::cout<<std::left).imbue(std::locale("en_US.UTF-8"));for(constautos:{"Capacity","Free","Available","Use%","Dir"})std::cout<<"│ "<<std::setw(width)<<s<<' ';for(std::cout<<'\n';autoconst&dir:dirs){std::error_code ec;conststd::filesystem::space_info si=std::filesystem::space(dir,ec);for(autox:{si.capacity,si.free,si.available,disk_usage_percent(si)})std::cout<<"│ "<<std::setw(width)<<static_cast<std::intmax_t>(x)<<' ';std::cout<<"│ "<<dir<<'\n';}}intmain(){constautodirs={"/dev/null","/tmp","/home","/proc","/null"};print_disk_space_info(dirs);}

上面的代码还是比较简单的,不过要想弄清楚,建议还是上机真正调试一下。

六、总结

通过上面的分析可以发现,抽象的层次就是不断的为终端用户减负而把具体的复杂实现隐藏在接口内部。这也给开发者提供了具象化的实践例子。这也符合软件设计中的抽象层解决一切的情况。