如何检查 Qt 中选定驱动器的可用空闲 space?
How to check the available free space of a selected drive in Qt?
我在 Windows 7.My 中使用 Qt5.6.2 目标是将 CustomDatafile 保存到 selected 驱动器(主要是 Pen 驱动器或本地驱动器或网络驱动器)。
所以在保存文件之前,我想检查 selected 路径的可用内存和写入权限。
由此thread我开始了解QStorageInfoclass。所以我写了下面的函数。
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 大小,驱动器未就绪。无论我 select 是什么驱动器,结果总是一样的。有人可以指出错误吗?我的问题有什么解决办法吗?提前谢谢你。
编辑 1:
如果我对 QStorage 构造器进行硬编码
QStorageInfo storage("D:");
Then Everything works fine.
If I give the path
QStorageInfo storage("D:\Application Cube DMU65mB.cba");
那就不行了。用户可以 select 任何驱动器(本地驱动器或可移动驱动器)。在 selecting 文件夹中,我从 QDialog 获取路径(此处未显示代码)。所以我想如果我只能从路径中获取驱动器信息,那么我想我的问题就解决了。现在,我怎样才能只得到驱动器名称?我可以通过解析从 QDialog 获得的路径来做,但有更好的解决方案吗?谢谢
编辑 2:
我已将构造函数更改为 QStorageInfo storage(path);。然后它适用于本地驱动器,但如果用户 selects 可移动驱动器(笔式驱动器),它不起作用。任何人都知道为什么它不适用于 Pen Drive?谢谢。
问题出在 QStorageInfo 的构造函数 class 的路径上。如果路径包含文件名,那么它将 NOT 工作。以下作品:
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());
}
以防万一有人必须支持 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;
}
我在 Windows 7.My 中使用 Qt5.6.2 目标是将 CustomDatafile 保存到 selected 驱动器(主要是 Pen 驱动器或本地驱动器或网络驱动器)。
所以在保存文件之前,我想检查 selected 路径的可用内存和写入权限。
由此thread我开始了解QStorageInfoclass。所以我写了下面的函数。
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 大小,驱动器未就绪。无论我 select 是什么驱动器,结果总是一样的。有人可以指出错误吗?我的问题有什么解决办法吗?提前谢谢你。
编辑 1: 如果我对 QStorage 构造器进行硬编码
QStorageInfo storage("D:"); Then Everything works fine. If I give the path QStorageInfo storage("D:\Application Cube DMU65mB.cba");
那就不行了。用户可以 select 任何驱动器(本地驱动器或可移动驱动器)。在 selecting 文件夹中,我从 QDialog 获取路径(此处未显示代码)。所以我想如果我只能从路径中获取驱动器信息,那么我想我的问题就解决了。现在,我怎样才能只得到驱动器名称?我可以通过解析从 QDialog 获得的路径来做,但有更好的解决方案吗?谢谢
编辑 2: 我已将构造函数更改为 QStorageInfo storage(path);。然后它适用于本地驱动器,但如果用户 selects 可移动驱动器(笔式驱动器),它不起作用。任何人都知道为什么它不适用于 Pen Drive?谢谢。
问题出在 QStorageInfo 的构造函数 class 的路径上。如果路径包含文件名,那么它将 NOT 工作。以下作品:
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());
}
以防万一有人必须支持 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;
}