当前位置: 首页 > 知识库问答 >
问题:

QT-QFile复制操作非常慢

傅长恨
2023-03-14

我正在开发一个应用程序,需要使用QT(5.6.1)将大量文件从一个文件夹复制到另一个文件夹

为此,我一直在使用QFile::copy()方法。这工作得很好,除了一件事:它非常慢。使用Windows资源管理器进行相同复制操作所需的时间是其两倍多。

想知道为什么会这样,我深入研究了QT源代码,在qfile中找到了这个。cpp,看起来很相关:

char block[4096];
qint64 totalRead = 0;
while(!atEnd()) {
    qint64 in = read(block, sizeof(block));
    if (in <= 0)
        break;
    totalRead += in;
    if(in != out.write(block, in)) {
        close();
        d->setError(QFile::CopyError, tr("Failure to write block"));
        error = true;
        break;
    }
}

据我所知,复制操作使用的是4096字节的缓冲区。这对于复制操作来说非常小,很可能是问题的原因。因此,我所做的是将缓冲区的大小更改为:

char block[4194304]; // 4MB buffer

然后,我重建了整个QT库,以包含此更改。然而,所有的修改都彻底打破了这个方法。现在,当我的应用程序尝试调用QFile::Copy()时,操作会立即中断(根据QtCreator的调试器,该方法甚至不会开始运行,而是在第一行之前停止)。调试器告诉我:

The inferior stopped because it received a signal from the Operating System.

Signal name :
SIGSEGV
Signal meaning :
Segmentation fault

我的c有点生疏,但我不明白仅仅改变数组的分配大小如何完全破坏方法......任何人都可以帮助:

1)告诉我为什么QFile: Copy()这么慢(我错过了什么吗?它不仅仅在我的PC上,在几台不同的机器上进行了测试)。问题实际上是我上面发布的代码还是完全是别的什么?2)告诉我为什么那个更改完全破坏了QFile

共有3个答案

仲孙才捷
2023-03-14

对于较新版本的Qt(我使用的是5.9.2),这似乎不再是一个问题。请查看中的QFileSystemEngine::copyFile()https://code.woboq.org/qt5/qtbase/src/corelib/io/qfilesystemengine_win.cpp.html代码使用本机函数CopyFile2。我的测试也证实了QFile::copy()与Windows上的本机实现相当。似乎Qt在这方面取得了一些进展。

翁和颂
2023-03-14

嗯,更改缓冲区大小没有什么好处,因为这显然只是派生函数engine()的一种退步-

最后,由于我的项目只应在Windows上运行,我最终使用了本机Win32 copy函数。所以我把电话换成:

QFile::copy(src, dest);

与:

CopyFileExW((LPCWSTR)src.utf16(), (LPCWSTR)dest.utf16(), 0, this, 0, 0);

请注意,您必须#包含“windows. h”才能使此调用正常工作。

龙亮
2023-03-14

您的更改损坏QFile的原因是堆栈上不适合4M缓冲区(默认堆栈大小通常类似于1M)。快速修复方法是:

std::vector<char> vec(4*1024*1024);
char *block = &vec.front();

向量将分配堆上的大缓冲区(并在完成后处理释放),您只需将block指向向量的前面。

我认为你对复制速度慢的原因的分析是正确的。

 类似资料:
  • 不知道为什么,模拟器无论切换界面还是动画都变得很慢,但是输入,很正常,没有慢。 尝试-1 我重新启动Xcode和模拟器,但没有任何效果。

  • 问题内容: 我正在VMWare下的SSD上用Node复制文件,但是性能很低。我已经用来衡量实际速度的基准测试如下: 但是,以下用于复制文件的节点代码非常慢,因此随后的运行不会使其速度更快: 运行方式为: 这里有什么问题,我该如何加快速度?我相信我可以通过调整缓冲区大小来更快地用C编写它。让我感到困惑的是,当我编写简单的几乎等同于pv的程序时,如下所示将stdin传递到stdout,它的速度非常快。

  • 你可以使用复制任务( Copy )去复制文件. 复制任务扩展性很强,能够过滤复制文件的内容, 映射文件名. 使用复制任务时需要提供想要复制的源文件和一个目标目录,如果你要指定文件被复制时的转换方式,可以使用 复制规则. 复制规则被 CopySpec 接口抽象,复制任务实现了这个接口. 使用 CopySpec.from() 方法指定源文件.使用 CopySpec.into() 方法指定目标目录. 例

  • 问题内容: 我们已经使用序列化实现了通用的深度复制机制。 需要维护的对象类数量一直在不断发展,这是我们继续使用通用克隆机制的原因。我们没有保持津津乐道的想法,并在200多个班。 不幸的是,Java中的序列化机制相对较慢,当系统处于峰值负载时,我们会遇到问题。 是否有任何建议的方法可以加快速度,或者(如果执行不正确的话)克隆对象的替代方法? 问题答案: 在Hibernate中(特别是在第二级缓存中)

  • 我有非常大的xls文件,其中包含两个表。我想把这两张表合并成一张,复制到新的工作簿上。但是当我尝试访问这个大的xls时,我会出现内存异常,如下所示: 我尝试使用xls的事件api:http://poi.apache.org/spreadsheet/how-to.html#event_api,但是使用它我们只能读取单元格值。但这里我需要复制到新的excel表。

  • 介绍一些常用的操作命令。