【问题标题】:Qt5 QFile::close() very slow for writingQt5 QFile::close() 写入速度非常慢
【发布时间】: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 位机器。感谢您的任何建议。

【问题讨论】:

    标签: c++ qt qt5 qfile


    【解决方案1】:

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

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

    【讨论】:

    • 正如我所怀疑的那样。因此,从用户的角度来看,我宁愿看到进度条达到 100% 然后复制完成,而不是达到 100% 后仍然需要再次等待相同的时间或更长的时间。复制完成。我此时的问题是,为什么 flush() 在返回之前实际将数据刷新到磁盘之前不会阻塞?如果我能做到这一点,那么进度条将更准确地向用户描述副本的状态。在这种情况下,我实际上对报告副本状态的准确性更感兴趣。
    • 那么在我调用flush()的时候有没有办法让写入刷新到磁盘?用户界面受到以下事实的阻碍:他们不知道为什么进度框处于 100% 状态的时间比到达那里的时间长。
    • 你可以试试syncfsync等。我不是 Windows 专家,所以我不知道该做什么。
    猜你喜欢
    • 2012-05-27
    • 2012-02-25
    • 2020-04-27
    • 2012-07-15
    • 1970-01-01
    • 1970-01-01
    • 2011-08-07
    • 1970-01-01
    • 2021-02-08
    相关资源
    最近更新 更多