+-
c – QFile :: flush()vs QFile :: close()
我正在我的类中实现一个方法,它将从TableView对象写入数据到CSV文件.但是,当程序运行时,程序会以非常慢的速度(3或4秒)将数据写入USB驱动器上的文件,但与系统的内部驱动器一起正常工作.这是因为我在编写文件后没有使用flush()或close()吗?

这是我的代码

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说

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

那么我应该调用close(),还是调用flush()更好,记录任何错误然后调用close()?

是否有任何其他修改,我必须做,以改善写操作?

最佳答案
> flush()vs. close()是一个红色的鲱鱼,它根本不会影响你的表现.
>销毁QTextStream会强制刷新文件.刷新文件很慢.每次迭代循环时,你都会破坏你的文本流!在循环外创建流!

这是Qt 5.1.1中的来源:

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

在Qt 5.1或更高版本上,如果要确保在文件关闭后刷新磁盘缓冲区,则应使用QSaveFile.只有这样才能让您确信,一旦您认为已完成保存,数据实际上就在磁盘上.
> QTextStream有自己的缓冲区.因此,如果要在刷新时捕获错误,则需要在流本身上使用flush()方法,而不是在QFile上.
>从GUI线程进行任何文件访问是一个非常糟糕的主意.任何时候阻止,你的UI线程也会阻塞.

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

如果您认为仅仅使用QMutex阻止对模型的并发访问就足够了,请再想一想.对模型进行的任何修改都可能会改变其结构,因此您的编写者需要正确处理模型发出的所有信号.这会使作者更加复杂.临时只读模型使您可以使响应式GUI对用户造成暂时的不便,同时最大程度地提高代码复杂性.

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驱动器非常慢.

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

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();
#if QT_VERSION >= QT_VERSION_CHECK(5,1,0)
    return os.status() == QTextStream::Ok && file.commit();
#else
    return os.status() == QTextStream::Ok;
#endif
}
点击查看更多相关文章

转载注明原文:c – QFile :: flush()vs QFile :: close() - 乐贴网