我正在实现类中的一个方法,它将把数据从一个TableView对象写入一个CSV文件。然而,当程序运行时,该程序以非常慢的速度(3或4秒)将数据写入USB驱动器上的文件,但是可以很好地处理系统的内部驱动器。这是因为在编写文件之后,我没有使用刷新()或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表示
调用QFile::刷新()并关闭该文件。来自刷新的错误将被忽略。
所以,我应该只调用close(),还是调用flush(),记录任何错误,然后调用close()更好呢?
还有什么其他的修改,我必须做,以改善写操作?
发布于 2013-09-30 14:34:28
flush() is close()是一条红线鲱鱼,它根本不影响你的性能。QTextStream的销毁会强制刷新文件。冲洗文件很慢。每次迭代循环时,您都在破坏您的文本流!在循环之外创建流!
这是来自QT5.1.1的源代码:
QTextStream::~QTextStream() { if (!d->writeBuffer.isEmpty()) d->flushWriteBuffer();}
在QT5.1或更高版本上,如果要确保文件关闭后磁盘缓冲区被刷新,则应该使用QSaveFile。只有这样,您才能保证,一旦您认为您已经完成了保存,数据实际上在磁盘上。QTextStream有自己的缓冲区。因此,如果您想在刷新时捕获错误,则需要在流本身上使用flush()方法,而不是在QFile上。setData调用都将失败。当然,您需要向用户表明这一点。模型的视图将是只读的,但这比阻塞整个GUI要友好得多。
如果您认为仅仅防止使用QMutex并发访问模型就足够了,那么请再考虑一下。对模型所做的任何修改都可能会改变其结构,因此您的作者需要正确地处理模型发出的所有信号。这将使作者更加复杂。一个临时的只读模型允许您拥有响应性GUI,同时对用户带来暂时的不便,而代码复杂度的增加是最小的。
类MyModel : public QStandardItemModel /*或任何您从*/ {true继承的类;Q_OBJECT Q_PROPERTY(bool可写读读isWritable写入通知writableChanged) bool m_writable;public:显式MyModel(QObject *父级):继承(父级),m_writable (真) {} Q_SLOT void (){ if (!m_writable)返回;m_writable= false;writableChanged(m_writable);} Q_SLOT void setReadWrite(){ if ( m_writable )返回;m_writable = true;m_writable= writableChanged (m_writable );} Q_SIGNAL void writableChanged( bool );bool isWritable() const {返回m_writable;} void (bool写的){ if (m_writable ==写的)返回;m_writable=写;emit (M_writable);} bool setData(const QModelIndex & index,const QVariant & val,int QVariant= Qt::EditRole) { if (!m_writable)返回false;返回继承的::setData(索引、val、角色);};您的重新编写的代码至少应该如下所示:
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
}发布于 2013-09-30 14:54:50
我可以告诉您,QFile::close()在函数的末尾被隐式调用,因为QFile对象的析构函数是在文件变量的作用域末尾调用的。来自QFile文档:
QFile::~QFile ()
Destroys the file object, closing it if necessary.您可能希望尝试的是操作系统的底层同步功能。AFAIK没有为此提供任何API,因此它不会是可移植的。当调用QFile::flush()函数时,一个可能发生的情况(至少在Linux上)是将数据从用户空间缓冲区释放到底层系统缓存,而不一定是磁盘。在linux/unix上,您需要fsync函数来确保文件实际写入磁盘。代码看起来类似于:
file.flush();
fsync( file.handle() );
file.close();我相信同样的代码也会在Windows上工作。
有关fflush vs fsync的更多信息,请参见Difference between fflush and fsync。
https://stackoverflow.com/questions/19096702
复制相似问题