Как я могу пропустить N строк QFile без временного сохранения их в QStrings? - PullRequest
0 голосов
/ 19 мая 2019

В основном, если я позвоню 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 Ответ

1 голос
/ 20 мая 2019

Qt не имеет API для поиска файла до следующего вхождения определенного байта без вывода прочитанных данных.

Вы можете подойти довольно близко, хотя:

QFile has 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 использует внутренний размер буфера 16 КБ:

изqtextstream.cpp:

static const int QTEXTSTREAM_BUFFERSIZE = 16384;

QIODevice использует тот же размер буфера:

из qiodevice_p.h:

#define QIODEVICE_BUFFERSIZE Q_INT64_C(16384)

Sidenote:

QTextStream также имеет readLineInto(QString *line, qint64 maxlen = 0), который динамически перераспределяет line, если maxlen равно 0 или длина строки чтения <<code>line->capacity().Но из-за кодирования чтение в QString всегда медленнее, чем чтение в QByteArray.

Функция, подобная readLineInto(...), не существует для QByteArray, однако.


Решение, использующее QIODevice::getChar(char *c) (предложенное в комментариях OP), также подходит, поскольку оно использует тот же внутренний буфер чтения, что и readLine, имеет битовые издержки для каждого вызова, но вызывающая сторона неприходится беспокоиться о строках длиннее выбранного размера буфера.

...