使用GetFileSize获取文件大小报告有效文件上的段

如何解决使用GetFileSize获取文件大小报告有效文件上的段

我有一个可以扫描文件并收集有关文件的元数据的应用程序。一种功能是获取文件的文件大小。为此,我正在使用winapi函数GetFileSizeEx(Handle,PLARGE_INTEGER)。参数需要文件HANDLE和对PLARGE_INTEGER的引用,也称为(*LARGE_INTEGER)。

要在Qt中获取文件HANDLE,建议here使用QFile::handle()获取文件句柄并将结果传递到_get_osfhandle(int)并将其转换为HANDLE

HANDLE handle = (HANDLE) _get_osfhandle(file.handle()).

使用此句柄,将其与PLARGE_INTEGER变量一起传递到[GetFileSizeEx(Handle,PLARGE_INTEGER)],如果操作失败,则返回0;如果操作成功,则返回!= 0

GetFileSize(HANDLE,PLARGE_INTEGER)返回:

  • 0(或失败),您可以根据GetLastError的列表使用error codes(作为开始,还有更多)来提供帮助。

  • 任何非零值表示成功

问题:

使用这种方法,我尝试对有效文件进行相同的操作,但是在调用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;
 }

我做错了吗?


查看随附的屏幕截图

enter image description here

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是“指向LARGE_INTEGER的指针”的别名。 PLARGE_INTEGER()是类型为“ LARGE_INTEGER的指针”的默认值初始化。对于所有指针来说,这样的初始化都是空指针。

这就是定义

PLARGE_INTEGER l = PLARGE_INTEGER();

等同于

LARGE_INTEGER* l = nullptr;

这意味着您将空指针传递给GetFileSizeEx

您需要创建一个实际的LARGE_INTEGER对象,并使用地址运算符&将指针传递给该对象:

LARGE_INTEGER l;
GetFileSizeEx(handle,&l);  // Pass pointer to the variable l
,

问题是您对PLARGE_INTEGER的处理不正确。您正在创建实际上没有指向任何地方的PLARGE_INTEGER(又名LARGE_INTEGER*)指针,这就是GetFileSizeEx()在尝试写出文件大小时崩溃的原因。

您需要分配一个LARGE_INTEGER(而不是PLARGE_INTEGER),然后将其内存地址传递给GetFileSizeEx(),例如:

static qint64 getWinAPIFileSize(QString filepath)
{
    QFile file(filepath);

    if (file.open(QIODevice::ReadOnly)) {
        int localFileHandle = file.handle();
        HANDLE handle = (HANDLE) _get_osfhandle(localFileHandle);
        LARGE_INTEGER l;
        if (GetFileSizeEx(handle,&l)) {
            return l.QuadPart;
        }
        qDebug() << getLastErrorMsg();
    }

    return QFileInfo(file).size();
}

话虽如此,在这种情况下,完全没有必要手动使用GetFileSizeEx()。根据其实现方式(我无法检查),QFileInfo.size()要么为您打开文件,要么直接从文件系统的元数据中查询文件的大小,而实际上根本没有打开文件:>

static qint64 getWinAPIFileSize(QString filepath)
{
    return QFileInfo(filepath).size();
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-