QTextStream behavior searching for a string not as expected
c++, qt, qtextstream
Solution
Obviously you get this behaviour because readLine() skips cursor by line size with line delimiter chars (either LF CRLF or CR depending on file). Buffer you get from this method does not contans those symbols, so you aren't taking these chars in your position calculations.
The solution is to read not by lines but by buffer. Here is your code, modified:
QFile file("h:/test.txt");
file.open(QFile::ReadOnly | QFile::Text);
QTextStream in(&file);
bool found = false;
uint pos = 0;
qint64 buffSize = 64; // adjust to your needs
do {
QString temp = in.read(buffSize);
int p = temp.indexOf("something");
if (p < 0) {
uint posAdj = buffSize;
if (temp.length() < buffSize)
posAdj = temp.length();
pos += posAdj;
} else {
pos += p;
found = true;
}
} while (!found && !in.atEnd());
in.seek(0);
QString text = in.read(pos);
cout << text.toStdString() << endl;
EDIT
The code above contains error due to word might be splitted by buffer. Here is a sample input that breaks stuff (assuming we seach for keks):
test test test test test test
test test test test test test keks
test test test test test test
test test test test test test
test test test test test test
test test test test test test
Solution
Here is complete code what works great with all inputs I tried:
#include <QFile>
#include <QTextStream>
#include <iostream>
int findPos(const QString& expr, QTextStream& stream) {
if (expr.isEmpty())
return -1;
// buffer size of same length as searched expr should be OK to go
qint64 buffSize = quint64(expr.length());
stream.seek(0);
QString startBuffer = stream.read(buffSize);
int pos = 0;
while(!stream.atEnd()) {
QString cycleBuffer = stream.read(buffSize);
QString searchBuffer = startBuffer + cycleBuffer;
int bufferPos = searchBuffer.indexOf(expr);
if (bufferPos >= 0)
return pos + bufferPos + expr.length();
pos += cycleBuffer.length();
startBuffer = cycleBuffer;
}
return pos;
}
int main(int argc, char *argv[])
{
Q_UNUSED(argc);
Q_UNUSED(argv);
QFile file("test.txt");
file.open(QFile::ReadOnly | QFile::Text);
QTextStream in(&file);
int pos = findPos("keks", in);
in.seek(0);
QString text = in.read(pos);
std::cout << text.toUtf8().data() << std::endl;
}
Problem
I have these few lines of code: ``` QFile file("h:/test.txt"); file.open(QFile::ReadOnly | QFile::Text); QTextStream in(&file); bool found = false; uint pos = 0; do { QString temp = in.readLine(); int p = temp.indexOf("something"); if (p < 0) { pos += temp.length() + 1; } else { pos += p; found = true; } } while (!found && !in.atEnd()); in.seek(0); QString text = in.read(pos); cout << text.toStdString() << endl; ``` The idea is to search a text file for a specific char sequence, and when found, load the file from the beginning to the occurrence of the searched text. The input I used for testing was: ``` this is line one, the first line this is line two, it is second this is the third line and this is line 4 line 5 goes here and finally, there is line number 6 ``` And here comes the strange part - if the searched string is on any of lines save for the last, I get the expected behavior. It works perfectly fine. BUT if I search for a string that is on the last line 6, the result is always 5 characters short. If it was the 7th line, the result would be 6 characters short and so on, when the searched string is on the last line, the result is always `lineNumber - 1` characters shorter. So, is this a bug or I am missing something obvious? EDIT: Just to clarify, I am not asking for alternative ways to do this, I am asking why do I get this behavior.