如何在 Qt 中检查选定驱动器的可用空间?

Posted

技术标签:

【中文标题】如何在 Qt 中检查选定驱动器的可用空间?【英文标题】:How to check the available free space of a selected drive in Qt? 【发布时间】:2017-12-15 15:22:35 【问题描述】:

我在 Windows 7 中使用 Qt5.6.2。我的目标是将 CustomDatafile 保存到选定的驱动器(主要是笔式驱动器或本地驱动器或网络驱动器)。

所以在保存文件之前,我想检查可用内存和所选路径的写入权限。

从thread 我开始了解 QStorageInfo 类。所以我写了下面的函数。

bool ImportExport::checkWriteAccessAndEnoughDriveSpace(const QString &path,QString &error)

   error = QString();
   int fileSizeMB = 100;//for testing purpose I am comparing with 100 MB. correct solution is to compare with size of the file.
   qDebug() << "path to QStorage: " <<path;
   QStorageInfo storage(path);
   //QStorageInfo storage = QStorageInfo::root();
   qDebug() << "export root path: " <<storage.rootPath();
   qDebug() << "volume name:" << storage.name();
   qDebug() << "fileSystemType:" << storage.fileSystemType();
   qDebug() << "size:" << storage.bytesTotal()/1000/1000 << "MB";
   qDebug() << "availableSize:" << storage.bytesAvailable()/1000/1000 << "MB";

   if (storage.isValid() && storage.isReady()) 
      if (!storage.isReadOnly()) 
         // check enough memory
         int MBavailable = storage.bytesAvailable()/1000/1000;
         if(MBavailable > fileSizeMB)
            return true;
         else
            error = tr("Not enough disk space, available disk space is only : ") + QString::number(MBavailable);
            return false;
         
      else
         error = tr("No permission to write to current folder ");
         qDebug() << error; // how to set this message as toolTip on the fileDialog
         return false;
      
   else
      error = tr("Selected drive validity: ")+ QString::number(storage.isValid()) +tr("or storage availability: ") +QString::number(storage.isReady());
      qDebug() << error; // how to set this message as toolTip
      return false;
   

这是调试输出:

path to QStorage:  "D:/Aluminium Demo DMU105mB.cba"
export root path:  ""
volume name: ""
fileSystemType: ""
size: 0 MB
availableSize: 0 MB
"Selected drive validity: 0or storage availability: 0"

如您所见,QStorageInfo 总是给我 0 大小,驱动器未准备好。无论我选择什么驱动器,结果总是相同的。任何人都可以指出错误吗?我的问题有什么解决方案吗?提前谢谢你。

编辑 1: 如果我对 QStorage 构造函数进行硬编码

QStorageInfo storage("D:"); 然后一切正常。 如果我给出路径 QStorageInfo storage("D:\Application Cube DMU65mB.cba");

然后就不行了。用户可以选择任何驱动器(本地驱动器或可移动驱动器)。在选择文件夹时,我从 QDialog 获取路径(此处未显示代码)。所以我想如果我只能从路径中获取驱动器信息,那么我想我的问题就解决了。现在,我怎样才能只获得驱动器名称?我可以通过解析从 QDialog 获得的路径来做到这一点,但有更好的解决方案吗?谢谢

编辑 2: 我已将构造函数更改为 QStorageInfo storage(path);。然后它适用于本地驱动器,但如果用户选择可移动驱动器(笔式驱动器),它就不起作用。任何人都知道为什么它不适用于 Pen Drive?谢谢。

【问题讨论】:

调用该函数时文件是否已经存在?如果将"d:\\" 硬编码为构造函数的参数会怎样? 您是否尝试过致电isValid() 来检查您是否提供了有效路径? @MrEricSir isValid() 总是错误的。即使驱动器存在并且我也具有写访问权限,我也无法理解为什么它是错误的? @KarstenKoop 如果已经存在的文件不是问题,我又做了一个检查。正如您所说,如果我在没有完整路径的情况下对“d:\\”进行硬编码,则可以正常工作。我已经更新了我的问题。谢谢 【参考方案1】:

问题在于给 QStorageInfo 类的构造函数的路径。如果路径包含文件名,那么它将工作。以下作品:

   QFileInfo info(fullPath);
   QString path = info.path();
   QStorageInfo storage(path);

注意:完整路径包含文件名,而路径不包含。

然后是下一个问题QStorageInfo::isReadOnly() 给你 false 即使你有写权限。由于 Windows-NFTS 文件系统,这不起作用。 所以诀窍是检查您是否可以成功创建临时文件。

  if (storage.isValid() && storage.isReady()) 
      //check write permission
      QString filename(path+"dummyTempJob.job"); //temp file, a workaround to check write access because QFileInfo isWritable and storage.isReadOnly() doesn't work for windows NTFS system
      QFile file(filename);
      if(file.open(QIODevice::WriteOnly))
          file.remove();//delete the temp file
          checkWriteAccess = true;
      else
         error = QObject::tr("No write permissions to %1.").arg(path);
         qCritical()<< error;
      
   else
      error = QObject::tr("Drive %1 is not available.").arg(storage.rootPath());
      qCritical() << error << QStringLiteral(" valid = %1, ready = %2").arg(storage.isValid()).arg(storage.isReady());
   

【讨论】:

【参考方案2】:

以防万一有人必须支持 Qt4。我在这里找到了解决方案:https://stackoverrun.com/de/q/342126

#ifdef _WIN32 //win
       #include "windows.h"
#else //linux
       #include <sys/stat.h>
       #include <sys/statfs.h>
#endif


bool GetFreeTotalSpace(const QString& sDirPath, double& fTotal, double& fFree)

       double fKB = 1024;

       #ifdef _WIN32

           QString sCurDir = QDir::current().absolutePath();
           QDir::setCurrent(sDirPath);

           ULARGE_INTEGER free,total;

           bool bRes = ::GetDiskFreeSpaceExA( 0 , &free , &total , NULL );

           if ( !bRes )
               return false;

           QDir::setCurrent( sCurDir );

           fFree = static_cast<__int64>(free.QuadPart)  / fKB;
           fTotal = static_cast<__int64>(total.QuadPart)  / fKB;

       #else // Linux

           struct stat stst;
           struct statfs stfs;

           if ( ::stat(sDirPath.toLocal8Bit(),&stst) == -1 )
               return false;

           if ( ::statfs(sDirPath.toLocal8Bit(),&stfs) == -1 )
               return false;

           fFree = stfs.f_bavail * ( stst.st_blksize / fKB );
           fTotal = stfs.f_blocks * ( stst.st_blksize / fKB );

       #endif // _WIN32

       return true;

【讨论】:

以上是关于如何在 Qt 中检查选定驱动器的可用空间?的主要内容,如果未能解决你的问题,请参考以下文章

Qt 驱动程序 Postgresql 可用但未加载

如何在不使用API 的情况下获得Google云端硬盘的可用空间?

查看磁盘空间命令

从汇编语言引导加载程序检查软盘是不是可用

Postgres声称驱动器空间不足,可用空间充足

Qt添加驱动——Qt数据库之添加MySQL驱动插件