Qt5 QFile :: close()编写速度非常慢

时间:2016-07-21 20:40:33

标签: c++ qt qt5 qfile

我使用QFile作为文件阅读器和文件编写器,从我的应用程序内部将文件复制到USB。我一直试图找出为什么我的文件复制到USB(带进度条)花了这么长时间。我终于发现,当我关闭用于写入的QFile对象时,close()操作可以在实际写入操作所花费的时间内完成。这些是非常大的文件,我读取/写入16384字节的块,然后我发送信号到GUI以增加用户查看的进度条。我最后在每次写入后添加了对flush()的调用,因为我认为这是因为out stream实际上还没有写入磁盘。这并没有什么不同。传出的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插件在VS7上安装Win7 32位盒子。感谢您的任何建议。

1 个答案:

答案 0 :(得分:1)

在编写时,操作系统可能只是将写入缓存在内存中(快速)。但是当你关闭文件时,它必须将所有数据刷新到磁盘(速度很慢 - 特别是如果它还没有实际写入任何)。因此,关闭文件必须等待操作系统实际将所有数据放入磁盘(USB),并且那时可能实际上是所有数据。

操作系统之所以做这样的事情当然是为了加快写入速度 - 而且通常他们可以在没有其他任何事情发生时将数据刷新到磁盘上(所以你不要这样做)真的注意到实际成本,因为它随着时间的推移而摊销,没有其他任何事情发生)。但是,如果你只是写,然后马上关闭,你会注意到。 注意:替代方案是写入调用速度较慢 - 您仍然会花费相同的实际时间。