我有一个阅读文件的问题,具体是我想做一个小字典.在我需要阅读的文件中有如下内容:
a Ph P6
a snsr CA
a b c fb Dj
a b c - book i+ BS
A except B gate oOPa y
a font kQ BU
[....]
Run Code Online (Sandbox Code Playgroud)
它有大约109.000行,文件大小约2MB.在我的QT应用程序中,我这样编码来读取和添加项目到QListWidget:
QString sWord;
QFile inFile("C:\\EV\\ev.index");
inFile.open(QIODevice::ReadOnly|QIODevice::Text);
QTextStream in(&inFile);
while(!in.atEnd())
{
sWord = in.readLine();
myListWidget->addItem(sWord); //myListWidget is a QListWidget
}
Run Code Online (Sandbox Code Playgroud)
但它读得太久了!起初我认为原因是我的应用程序逐行读取,所以我再次编码它:
QString data;
QStringList listWord;
QFile inFile("C:\\EV\\ev.index");
inFile.open(QIODevice::ReadOnly|QIODevice::Text);
QTextStream in(&inFile);
data.append(in.readAll());
listWord.append(data.split('\n'));
myListWidget->addItems(listWord);
inFile.close();
Run Code Online (Sandbox Code Playgroud)
它工作得更快!(自应用程序启动以来大约5秒),仍然很长,我希望它读得更快.我该怎么办?
列表小部件的布局需要太长时间.将列表小部件的uniformItemSizes属性设置为true.这避免了昂贵的布局操作.另一种方法是将layoutMode属性设置为QListView::Batched.这避免了必须一次昂贵地布置所有物品.
不要使用QListWidget,如果一个较低的开销QListView会做.
应批量添加大量元素,即不要逐个将元素插入模型中.在发出rowsInserted或columnsInserted仅发出一次信号的原子操作中插入每个批次中的元素.
您不能在GUI线程中执行任何文件加载.这是许多应用程序中糟糕的用户体验的来源,并且必须因为大量的嘲笑而气馁.不要这样做.
以下是将所有这些考虑在内的最小示例.
// https://github.com/KubaO/stackoverflown/tree/master/questions/filemodel-18548048
#include <QtWidgets>
#include <QtConcurrent>
void makeLines(QBuffer &buf, int count = 1000000) {
buf.open(QIODevice::WriteOnly | QIODevice::Text);
char line[16];
for (int i = 0; i < count; ++i) {
int n = qsnprintf(line, sizeof(line), "Item %d\n", i);
buf.write(line, n);
}
buf.close();
}
struct StringListSource : QObject {
Q_SIGNAL void signal(const QStringList &);
void operator()(const QStringList &data) { emit signal(data); }
Q_OBJECT
};
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
QListView view;
QStringListModel model;
StringListSource signal;
QObject::connect(&signal, &StringListSource::signal, &model, &QStringListModel::setStringList);
QtConcurrent::run([&signal]{
QBuffer file;
signal({"Generating Data..."});
makeLines(file);
signal({"Loading Data..."});
QStringList lines;
if (file.open(QIODevice::ReadOnly | QIODevice::Text))
while (!file.atEnd())
lines.append(QString::fromLatin1(file.readLine()));
file.close();
signal(lines);
});
view.setModel(&model);
view.setUniformItemSizes(true);
view.show();
return app.exec();
}
#include "main.moc"
Run Code Online (Sandbox Code Playgroud)