我如何跳过QFile的N行而不将它们临时存储在QString中?

时间:2019-05-19 12:27:13

标签: c++ qt qfile

基本上,如果我呼叫QFile::readLine,将复制QFile的整个行并将其粘贴到char*QByteArray中。如果我想跳过999行以直接转到感兴趣的行(第1000行),那么我将无缘无故地复制并粘贴前999行,而我只想跳过它们。

我知道istream::ignore使用户可以跳过任何数量的字符,直到找到分隔符为止,所以

std::ifstream file("file.txt");

for (auto i = 0u; i < 999u; ++i)
    file.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

std::string str;
getline(file, str); // The 1,000th line is copied & pasted into str

将使您直接进入第1000行,而不会浪费任何时间进行复制和粘贴。如何使用QFile做同样的事情?

1 个答案:

答案 0 :(得分:1)

Qt没有用于在下一个特定字节出现之前查找文件而不输出读取数据的API。

尽管如此,您还是可以很亲近的

QFile具有QIODevice::readLine(char *data, qint64 maxSize),它读入预分配的缓冲区,可以这样使用:

QFile f("..."); f.open(...);

int maxSize = 1024; // guess that 1kb will be enough per line
QByteArray lineData(maxSize, '\0');
int skipLines = 100;
while(f.readLine(lineData.data(), maxSize) > 0 && skipLines > 0) {
    --skipLines;
}

此调用readLine()重用了预先分配的缓冲区。

您可以看到,这里的关键部分是猜测哪种预分配大小最佳。如果您的行长超出了猜测的大小,那么您将跳过不到100行,因为每条较长的行都需要进行多次读取。

QTextStream使用的内部缓冲区大小为16kb:

来自qtextstream.cpp:

static const int QTEXTSTREAM_BUFFERSIZE = 16384;

QIODevice使用相同的缓冲区大小:

来自qiodevice_p.h:

#define QIODEVICE_BUFFERSIZE Q_INT64_C(16384)

旁注:

QTextStream还具有readLineInto(QString *line, qint64 maxlen = 0),如果line为0或读取行的长度为<maxlen,则会动态重新分配line->capacity()。但是,由于编码的原因,读入QString总是比读入QByteArray慢。

readLineInto(...)并不像QByteArray这样的功能。


使用QIODevice::getChar(char *c)(在OP注释中提出)的解决方案也是合适的,因为它使用与readLine相同的内部读取缓冲区,每次调用都有一些开销,但是调用者却没有不必担心行长会超过选定的缓冲区大小。