QFile :: flush()vs QFile :: close() [英] QFile::flush() vs QFile::close()

查看:3197
本文介绍了QFile :: flush()vs QFile :: close()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在我的类中实现一个方法,它会将数据从TableView对象写入CSV文件。然而,当程序运行时,程序以非常慢的速率(3或4秒)将数据写入USB驱动器上的文件,但对系统的内部驱动器工作正常。这是因为我没有使用flush()或close(),写入文件后

I am implementing a method in my class, which will write out data from a TableView Object to a CSV file. However when the program runs, the program writes the data to the file on a USB drive at a very slow rate(3 or 4 seconds), but works fine with the system's internal drive. Is this because i have not used flush() or close(), after writing the file ??

这是我的代码

bool ThicknessCalibrationDataDisplay::WriteCSVFileChanges()
{
    QModelIndex tableViewModelindex =  tableViewModel_->index(0,0);

    QFile file(CSVFileName_);
    if(!file.exists())
        return false;

    if(!file.open(QIODevice::WriteOnly))
        return false;


    for(int i = 0; i < totalRows_ ; i++)
    {
        for(int j = 0 ; j < totalColumns_; j++)
        {
            tableViewModelindex =  tableViewModel_->index(i,j);
            qDebug()<<tableViewModelindex.data();
            QString text = tableViewModelindex.data().toString();
            QTextStream OutputStream(&file);

            if(j == totalColumns_ - 1)
                OutputStream<<"\n\r";
            else
                OutputStream<<',';

        }
    }

}

这是我的代码早,现在我打算关闭文件流,为一个优雅的退出。
QFile :: close()的Qt API说

This was my code earlier, and now i plan to close the file stream, for a graceful exit. The Qt API for QFile::close() says


调用QFile :: flush()并关闭文件。错误从冲洗
忽略。

Calls QFile::flush() and closes the file. Errors from flush are ignored.

所以我应该调用close(),或者最好调用flush ),记录任何错误,然后调用close()?

So should i just call close(), or is it better to call flush(), log any errors and then call close() ?

是否有其他修改,我必须改进写操作?

Is there any other modification, that i have to make, to improve the write operation ?

推荐答案


  1. flush() code> close()是一个红色的鲱鱼,它不会影响你的表现。

  1. The flush() vs. close() is a red herring, it doesn't impact your performance at all.

破坏 QTextStream 强制刷新文件。刷新文件。每次迭代循环时,你都会破坏你的文本流!创建循环外的流!

Destruction of a QTextStream forces a flush of the file. Flushing the file is slow. You're destroying your text stream every time you iterate through the loop! Create the stream outside of the loop!

以下是来自Qt 5.1.1的源代码:

Here's the source, from Qt 5.1.1:

QTextStream::~QTextStream()
{
    if (!d->writeBuffer.isEmpty())
        d->flushWriteBuffer();
}

在Qt 5.1或更高版本上,应该使用 QSaveFile 如果要确保在文件关闭后刷新磁盘缓冲区。

On Qt 5.1 or newer, you should be using QSaveFile if you want to ensure that the disk buffers are flushed once the file is closed. Only this gives you assurance that once you think you're done saving, the data is in fact on the disk.

QTextStream

QTextStream has its own buffers. So, if you want to catch errors while flushing, you need to use the flush() method on the stream itself, not on the QFile.

从GUI线程执行任何文件访问是一个糟糕的主意。任何时候任何阻塞,你的UI线程也阻塞。

It's a very bad idea to do any file access from the GUI thread. Any time anything blocks, your UI thread blocks as well.

现在的问题是:你如何使你的模型安全从另一个线程访问?如果使用自定义模型,则可能只需要在写入文件的过程中将模型切换为只读模式。只读模式将是模型的自定义属性,因此所有 setData 调用将失败。你当然需要向用户表明这一点。模型的视图将是只读的,但是比阻塞整个GUI更友好。

Now the question is: how do you make your model safe to access from another thread? If you use a custom model, you probably only need to switch the model into a read-only mode for the duration of writing the file. The read-only mode would be a custom property of the model, such that all setData calls would fail. You'd of course need to indicate this to the user. The views of the model would be read-only, but that's much more friendly than blocking the entire GUI.

如果你认为只是阻止并发访问模型, QMutex就够了,再想想。对模型进行的任何修改都可能改变其结构,因此您的作者需要正确处理模型发出的所有信号。这将使作者更复杂。临时只读模型允许您使用响应式GUI,对用户造成暂时不便,代码复杂性增加最小。

If you think that merely preventing concurrent access to the model with a QMutex would be enough, think again. Any modifications made to the model may potentially change its structure, so your writer would need to properly handle all signals emitted by model. This would make the writer much more complex. A temporarily read-only model lets you have responsive GUI with a temporary inconvenience to the user, at a minimal increase in code complexity.

class MyModel : public QStandardItemModel /*  or whatever other class you derive from */ {
    typedef QStandardItemModel inherited;
    Q_OBJECT
    Q_PROPERTY(bool writable READ isWritable WRITE setWritable NOTIFY writableChanged)
    bool m_writable;
public:
    explicit MyModel(QObject * parent) : inherited(parent), m_writable(true) {}
    Q_SLOT void setReadOnly() {
        if (!m_writable) return;
        m_writable = false; 
        emit writableChanged(m_writable);
    }
    Q_SLOT void setReadWrite(){
        if (m_writable) return;
        m_writable = true; 
        emit writableChanged(m_writable);
    }
    Q_SIGNAL void writableChanged(bool);
    bool isWritable() const { return m_writable; }
    void setWritable(bool writable) {
       if (m_writable == writable) return;
        m_writable = writable; 
        emit writableChanged(m_writable);
    }
    bool setData(const QModelIndex & index, const QVariant & val, int role = Qt::EditRole) {
        if (! m_writable) return false;
        return inherited::setData(index, val, role);
    }
};


  • 某些USB驱动器速度非常慢。

  • Some USB drives are abysmally slow.

    您返工的代码至少应该如下所示:

    Your reworked code should, at the minimum, look as follows:

    bool ThicknessCalibrationDataDisplay::WriteCSVFileChanges()
    {
    #if QT_VERSION < QT_VERSION_CHECK(5,1,0)
        QFile file(CSVFileName_);
    #else
        QSaveFile file(CSVFileName_); // does a disk commit at the end
    #endif
        if(!file.exists())
            return false;
    
        if(!file.open(QIODevice::WriteOnly))
            return false;
    
        QTextStream os(&file);
        for(int i = 0; i < totalRows_ ; i++)
        {
            for(int j = 0 ; j < totalColumns_; j++)
            {
                QModelIndex index = tableViewModel_->index(i,j);
                qDebug() << index.data();
                os << index.data();
                if(j == totalColumns_ - 1)
                    os<<"\n\r";
                else
                    os<<',';
    
            }
        }
        os.flush();
        return os.status() == QTextStream::Ok;
    }
    

    这篇关于QFile :: flush()vs QFile :: close()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆