【问题标题】:File Copy Disable Buffering with Qt文件复制禁用 Qt 缓冲
【发布时间】:2018-05-02 20:43:40
【问题描述】:

我正在使用 Qt 框架编写文件复制器数据备份软件,并且在数据复制中遇到“缺陷”。

如果我将数据从 SSD 复制到 HDD,SSD 读取数据的速度要比 HDD 写入数据的速度快得多。因此,读取的数据在写入 HDD 之前会填充缓冲区。

这不会是一个问题,只是当缓冲区被填满时数据复制的进度表会停止,然后当它被清空时,它会竞相再次被填满。所以进度表指示一堆进度,然后它停止,然后它指示进度,然后停止等等。与以恒定速率写入数据时发生的持续进度相比,它看起来很丑。

Qt 有没有办法解决这个问题?我尝试使用QFile::flush(),但没有帮助。

我们有来自 Win32 api 的FlushFileBuffers,但文档说在每次写入磁盘驱动器设备后使用它时效率低下,而许多写入是单独执行的。

我们可以使用FILE_FLAG_NO_BUFFERINGFILE_FLAG_WRITE_THROUGH 标志调用CreateFile 函数,但是有没有办法使用QFile 来做到这一点?

然后我们可以选择完全关闭目标磁盘的缓存为here

最优雅的解决方案是什么?

以下是相关代码:

QFile sourceFile;
QFile targetTempFile;
// ...
QByteArray buffer;
for (int count = 0; !(buffer = sourceFile.read(1000000)).isEmpty() && cancel == false; count++)
{
    int readSize = buffer.size();
    targetTempFile.write(buffer);
    //targetTempFile.flush();
    setProgressMeters(readSize, fileSize, jobSize);
    setTimeLabels(startTime.elapsed(),readSize);
}

【问题讨论】:

  • @JoshOrenberg winapi 函数上的AW 后缀与charwchar_t 接口有关。现代的默认设置是将ApiW 别名为Api,即CopyFileExCopyFileExW 相同。
  • 那个 CopyFile2 怎么样 - 它只是一个具有不同参数结构的 CopyFileEx 吗?

标签: qt file winapi


【解决方案1】:

对于 Windows 上的高性能文件复制,您应该使用 CopyFileEx,而不是 QFileCopyFileEx 将使用较低级别的 API,这可能会导致现代硬件上的零拷贝复制。见this example of CopyFileEx integration with Qt

要从QFileDevice(即QFile/QSaveFile)获取本机HANDLE,并在QFile 上使用ReOpenFile,请参阅this answer

【讨论】:

  • 如果从通过 worker 移动到工作线程的工作对象运行,如何将 CopyFileEx 示例修改为线程安全的->moveToThread(workerThread);打电话?
  • @JoshOrenberg 这个问题不属于这里 - 在您想查看修改的地方询问。但总的来说,Copier 本质上是线程安全的,因为它无论如何都在内部使用工作线程 - c.f. QtConcurrent::run。将Copier 移动到任何其他线程是没有意义的。
猜你喜欢
  • 2015-07-07
  • 2016-09-23
  • 2010-09-11
  • 2023-03-10
  • 1970-01-01
相关资源
最近更新 更多