如何跳过 QFile 的 N 行而不将它们临时存储在 QStrings 中?
Posted
技术标签:
【中文标题】如何跳过 QFile 的 N 行而不将它们临时存储在 QStrings 中?【英文标题】:How can I skip N lines of a QFile without temporarily storing them in QStrings? 【发布时间】:2019-05-19 12:27:13 【问题描述】:基本上,如果我调用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
做同样的事情?
【问题讨论】:
你可以循环调用getChar
,直到你看到999个换行符。
【参考方案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)
,如果maxlen
为0 或读取行的长度为line->capacity(),则动态重新分配line
。但是,由于编码的原因,读入QString
总是比读入QByteArray
慢。
不过,QByteArray
不存在像 readLineInto(...)
这样的函数。
使用QIODevice::getChar(char *c)
(在 OP cmets 中提出)的解决方案也很合适,因为它使用与readLine
相同的内部读取缓冲区,每次调用都有一点开销,但调用者不必担心超过所选缓冲区大小的行。
【讨论】:
以上是关于如何跳过 QFile 的 N 行而不将它们临时存储在 QStrings 中?的主要内容,如果未能解决你的问题,请参考以下文章