如何检查QT中选定驱动器的可用可用空间

How to check the available free space of a selected drive in Qt?

本文关键字:驱动器 空间 何检查 检查 QT      更新时间:2023-10-16

我在Windows 7中使用QT5.6.2。

因此,在保存文件之前,我想检查所选路径的可用内存并写入访问。

从这个线程中,我了解了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 Contructor

的编码

qstorageinfo存储(d:; quot;);然后一切正常。如果我给路径qstorageinfo存储(d: application cube dmu65mb.cba&quot;

那么它不起作用。用户可以选择任何驱动器(本地驱动器或可移动驱动器)。在选择文件夹时,我从qdialog获取路径(此处未显示代码)。因此,我认为,如果我只能从路径上获得驱动器不足,那么我想解决了我的问题。现在,如何仅获得驱动器名称?我可以通过解析从Qdialog获得的路径来做到这一点,但是有什么更好的解决方案吗?谢谢

编辑2:我已经更改了 QStorageInfo Storage(PATH); 。然后,它适用于本地驱动器,但是如果用户选择可移动驱动器(PEN驱动器),则无效。有人知道为什么它在笔驱动器上不起作用吗?谢谢。

问题在于给出qstorageinfo类构造函数的路径。如果路径包括文件名,则将不工作。以下工作:

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

注意:FullPath包含文件名,而路径则没有。

然后来了下一个问题qstorageinfo :: isreadonly()即使您有写入访问,也会给您错误。由于Windows-NFTS文件系统,这无效。因此,诀窍是检查您是否可以sucecsss创建一个临时文件。

  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());
   }

以防万一必须支持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;
}