如何在Qt中从txt文件加载大数据

How to load large data from txt file in Qt

本文关键字:文件 加载 数据 txt 中从 Qt      更新时间:2023-10-16

我需要尽快将一个包含 500 万数据(即字符串,只有一个单词,每个单词 9 个字符用换行符分隔)的 txt 文件加载到 QVector 中。代码现在工作正常,但是,如果用户点击上传,应用程序需要 3-5 秒来加载此数据以进行进一步操作。我需要减少加载此数据的时间。处理此问题的正确方法是什么?我对Qt/STL/Boost没问题。不过我更喜欢Qt。我用于此任务的代码是Qt文档中建议的代码,即

QFile file("in.txt");
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
return;
QTextStream in(&file);
while (!in.atEnd()) {
QString line = in.readLine();
process_line(line);
}

试试这个:

我测试了它并在2.1 秒内读取了文件。

我在阅读前reserve向量,并使用QElapsedTimer来获得阅读时间。

void MainWindow::readDataText()
{
QString filePath = "F:\Qt\Big_File\Big_File\data.txt";
QVector<qint64> *vector = new QVector<qint64>;
vector->reserve(5000000);
QElapsedTimer timer;
QFile readFile(filePath);
if(!readFile.open(QFile::ReadOnly | QFile::Text))
{
// Can't Open File.
}
else
{
QByteArray data;
timer.start();
for (int var = 0; var < 5000000; ++var)
{
vector->insert(var, (readFile.readLine()).toInt());
}
qint64 time = timer.elapsed();
ui->txtReadTimeText->setText(QString::number(time));
}
readFile.close();
}

如果您的文件是二进制的,也会更好。

另一种解决方案是使用readAll()函数并在116 毫秒内读取文件,稍后处理(拆分为"")数据,如下所示:

void MainWindow::readDataText()
{
QString filePath = "D:\ProjectTest\ProjectTest\data.txt";
QByteArray data;
data.reserve(5000000);
QElapsedTimer timer;
QFile readFile(filePath);
if(!readFile.open(QFile::ReadOnly | QFile::Text))
{
// Can't Open File.
}
else
{
timer.start();
data = readFile.readAll();
qint64 time = timer.elapsed();
ui->txtReadTimeText->setText(QString::number(time));
}
readFile.close();
}

您的示例代码实际上隐式进行解码。它从文件中读取8位编码的文本,并将其转换为内部使用16位Unicode编码的QString

如果不使用QTextStream,而是直接使用普通QFile,并使用这种readLine返回QByteArray的方法读取它,换句话说,"原始"文件内容,您可能会获得很大的加速。这样做的目的是避免为整个文件内容创建QString对象。

如果您有 500 万行,那么如果您将它们存储在内存中,您还将节省大量内存占用QByteArray,而不是QString.仅当您实际要在 GUI 中显示文本时才转换为QString


注意:注意文本编码!任何文件中的任何文本始终被编码,即使特别是说英语的人可能没有意识到这一点。最直接的编码是 7 位 ASCII,很多纯英文文本其实都是这个,几乎每个编码包括 UTF-8 其实都是 7 位 ASCII 的超集,所以 7 位 ASCII 文件几乎可以使用任何编码加载。但是对于多语言文本,您需要知道文件使用的编码,否则您将得到重音和其他特殊字符(如 ÄÅÁÀÃ)的错误。UTF8是唯一可以存储"所有内容"的编码,其他编码(如Latin1)是为特定语言家族设计的。

注2:在大多数情况下,QByteArray实际上对应于std::stringQString更像是std::wstring.并不是说这些是相同的 1:1 比赛,但将它们视为相似会有所帮助。