【发布时间】:2016-11-25 14:56:12
【问题描述】:
我使用 QFile 作为文件读取器和文件写入器,将文件从我的应用程序内部复制到 USB。我一直在试图弄清楚为什么我的文件复制到 USB(带有进度条)需要这么长时间。我终于发现,当我关闭用于写入的 QFile 对象时,close() 操作可能会远远超过实际写入操作所花费的时间。这些是非常大的文件,我读/写 16384 字节的块,然后我向 GUI 发送信号以增加用户查看的进度条。我最终在每次写入后添加了对 flush() 的调用,因为我认为这是输出流实际上尚未写入磁盘的结果。这并没有什么不同。传出 QFile 对象的关闭仍然需要比写入时间更长的时间(复制之前和之后的时间,以及每个 QFile::close() 调用之前和之后的时间,时间代码已被删除易于阅读,我也调试并看到它发生)。当然,不调用 close() 函数也无济于事,因为 QFile 对象的破坏会导致它被调用。
我的代码如下(减去错误检查,目标空间检查等):
void FileCopy::run()
{
QByteArray bytes;
int totalBytesWritten = 0;
int inListSize = inList.size();
for (int i=0; !canceled && i<inListSize; i++)
{
QString inPath = inList.at(i).inPath;
QString outPath = inList.at(i).outPath;
QFile inFile(inPath);
QFile outFile(outPath);
int filesize = inFile.size();
int bytesWritten = 0;
if (!inFile.open(QIODevice::ReadOnly))
{
return;
}
if (!outFile.open(QIODevice::WriteOnly))
{
inFile.close();
return;
}
// copy the FCS file with progress
while (!canceled && bytesWritten < filesize)
{
bytes = inFile.read(MAXBYTES);
qint64 outsize = outFile.write(bytes);
outFile.flush();
if (outsize != bytes.size())
{
break;
}
bytesWritten += outsize;
totalBytesWritten += outsize;
Q_EMIT signalBytesCopied(totalBytesWritten, i+1, inListSize);
QThread::usleep(100); // allow time for detecting a cancel
}
inFile.close();
outFile.close();
}
// Other error checking done here
}
谁能找到通过这个的方法?实际上,我希望进度条移动得更慢,更准确地向用户显示副本的状态,而不是让进度条在不到复制所需时间的一半并接近实际完成的时间内读取 100%。
我也尝试过使用 QSaveFile 而不是 QFile 作为输出,但是 QSaveFile::commit() 有同样的问题,提交比完成实际的复制循环花费更多的时间。我认为这是因为在底层,它使用与 QFile 相同的功能,源自 QIoDevice。
我曾考虑改用标准流,但希望在此应用程序中完成文件处理的方式保持一定的一致性。不过,如果 QFile::close() 需要这么长时间才能关闭,这是有可能的。或者标准流可能有同样的问题?
我正在使用 Qt5.1.1 和 Qt 1.2.2 VS 插件开发带有 VS2010 的 Win7 32 位机器。感谢您的任何建议。
【问题讨论】: