【发布时间】:2020-12-08 23:52:22
【问题描述】:
我有一个应用程序可以扫描文件并收集有关文件的元数据。一个功能是获取文件的文件大小。为此,我使用了winapi 函数GetFileSizeEx(Handle, PLARGE_INTEGER)。这些参数需要一个文件 HANDLE 和一个对 PLARGE_INTEGER aka (*LARGE_INTEGER) 的引用。
要在Qt中获取文件HANDLE,建议here使用QFile::handle()获取文件句柄并将结果传递给_get_osfhandle(int)并将其转换为句柄。
HANDLE handle = (HANDLE) _get_osfhandle(file.handle()).
使用此句柄,将其与 PLARGE_INTEGER 变量一起传递到 [GetFileSizeEx(Handle, PLARGE_INTEGER)] 如果操作失败则返回 0,如果操作成功则返回 != 0。
GetFileSize(HANDLE, PLARGE_INTEGER) 返回:
-
0(或失败),可以根据error codes这个列表使用GetLastError(作为开始,还有很多)来帮助。
-
任何表示成功的非零值
问题:
使用这种方法,我在有效文件上尝试相同的方法,但是在调用 GetFileSizeEx(Handle, PLARGE_INTEGER) 时我得到了一个 SEGV。我在调用QFile::open(QIODevice::ReadOnly) 之前和之后都尝试过这个测试,但是它失败了。
int localHandle = file.handle(); // handle returns -1 as expected
bool localOpen = file.open(QIODevice::ReadOnly);
if (localOpen) {
int localFileHandle = file.handle(); // returns a valid >0 handle value
HANDLE handle = (HANDLE) _get_osfhandle(localFileHandle); // returns a valid > 0 handle value
PLARGE_INTEGER l = PLARGE_INTEGER(); // representation value of 0
BOOL b = GetFileSizeEx(handle, l); // segv
if (!b) {
qDebug() << getLastErrorMsg();
return QFileInfo(filepath).size();
}
return l->QuadPart;
}
我是不是做错了什么?
见附件截图
MVCE
#include <QCoreApplication>
#include "windows.h"
#include <comdef.h>
#include <QFile>
#include <QDebug>
#include <QString>
#include <QFileInfo>
#include <windows.h>
#include <fileapi.h>
#include <io.h>
static QString toString(HRESULT hr)
{
_com_error err{hr};
const TCHAR* lastError = err.ErrorMessage();
return QStringLiteral("Error 0x%1: %2").arg((quint32)hr, 8, 16, QLatin1Char('0'))
.arg(lastError);
}
static QString getLastErrorMsg()
{
DWORD lastError = GetLastError();
QString s = toString(HRESULT_FROM_WIN32(lastError));
return s;
}
static qint64 getWinAPIFileSize(QString filepath)
{
QFile file(filepath);
if (!file.exists()) {
return 0;
}
int localHandle = file.handle(); // handle returns -1 as expected
bool localOpen = file.open(QIODevice::ReadOnly);
if (localOpen) {
int localFileHandle = file.handle(); // returns a valid >0 handle value
HANDLE handle = (HANDLE) _get_osfhandle(localFileHandle); // returns a valid > 0 handle value
PLARGE_INTEGER l = PLARGE_INTEGER(); // representation value of 0
BOOL b = GetFileSizeEx(handle, l); // segv
if (!b) {
qDebug() << getLastErrorMsg();
return QFileInfo(filepath).size();
}
return l->QuadPart;
}
return QFileInfo(filepath).size();
}
int main(int argc, char* argv[])
{
QCoreApplication a(argc, argv);
QString src = QString("C:/Users/CybeX/.bash_history"); // change path to a valid file on your PC
qint64 size = getWinAPIFileSize(src);
qDebug() << size;
return a.exec();
}
【问题讨论】:
-
你知道
PLARGE_INTEGER是什么吗?
标签: c++ qt winapi file-io filesize