Reading a txt file using QTextStream C++ - c++

I am making a small program I have done before in Java however I want to try and get the same working in C++. The idea is to merge two text files
file1:
a
b
c
file2:
1
2
3
output file should read:
a1
b2
c3
I have looked at the QTextStream docs and this was the suggested code to read a file by line into strings
QFile file(input); // this is a name of a file text1.txt sent from main method
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
{
return 1;
}
QTextStream in(&file);
QString line = in.readLine();
while (!line.isNull())
{
line = in.readLine();
}
Yet for some reason nothing is being loaded from the file at all. I proved this by printing 'line' to console and got nothing.
So any ideas? All I want is to read the file and end up with a string like this
QString text1 = "a\n2\n3"
I'd do this for both files, split the strings into QStringList (most likely) join them together in the format I want and write them to a 3rd txt file.

Why do you read line by line if you want the entire file?
QString line = in.readAll();
ALso, your while loop is wrong, you need to while (!in.atEnd()) for the text stream instead of checking if the string is null.
readLine won't include the new line symbol.
Anyway, it would be much easier to open both files at the same time and construct your string on the go instead of splitting and joining.
QFile f1("h:/1.txt");
QFile f2("h:/2.txt");
f1.open(QIODevice::ReadOnly | QIODevice::Text);
f2.open(QIODevice::ReadOnly | QIODevice::Text);
QString s;
QTextStream s1(&f1);
QTextStream s2(&f2);
for (int i = 0; i < 3; ++i) {
s.append(s1.readLine());
s.append(s2.readLine());
if (i != 2)s.append("\n");
}

If the file name does not contain full path, but you are very sure that the file is located in the same directory as your application, use the applications path like this:
QString filename = QCoreApplication::applicationDirPath() + "/" + input;

Try this block-:
while(!in.atEnd())
{
QString line = in.readLine();
....
}
do you get output using this while loop?

Related

How to delete a line from a txt file in Qt?

My txt file (CopyBook.txt) contains for example 10 lines. I want to delete the third one.
I have this code:
QString fname = "C://Users//Tomahawk//Desktop//copy//CopyBook.txt";
QFile file(fname);
if (file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append))
{
QTextStream edit(&file);
QString line;
int reachForLine = 0;
int neededLine = 3;
while (reachForPage != pageCounter)
{
line = edit.readLine();
reachForPage++;
}
}
So you can see I use "while" to reach for the line i want to delete. But I haven't found any method in Qt that allows me to do it. In future I want to use the ability of deleting lines to replace them with another ones. So how do I delete it?
One way to do it would be to read all of the lines into a QStringList, modify the QStringList, and then turn around and write its contents back to the file again, like this:
int main(int argc, char ** argv)
{
const QString fname = "C:/Users/Tomahawk/Desktop/copy/CopyBook.txt";
QStringList lines;
// Read lines of text from the file into the QStringList
{
QFile inputFile(fname);
if (inputFile.open(QIODevice::ReadOnly | QIODevice::Text))
{
QTextStream edit(&inputFile);
while (!edit.atEnd()) lines.push_back(edit.readLine());
}
inputFile.close();
}
// Delete the third line from the QStringList
if (lines.length() > 2) lines.removeAt(2); // 0==first line, 1==second line, etc
// Write the text in the QStringList back to the file
{
QFile outputFile(fname);
if (outputFile.open(QIODevice::WriteOnly | QIODevice::Text))
{
QTextStream edit(&outputFile);
for (int i=0; i<lines.size(); i++) edit << lines[i] << Qt::endl;
}
outputFile.close();
}
return 0;
}
You could also perform any replacements/insertions you want to make on the QStringList object, before writing it back to the file.
Note that this approach does use up RAM proportional to the size of the file, so for very large files (e.g. gigabytes long) you would probably want to use the create-a-second-file-and-then-rename approach proposed by #TedLyngmo in his comment, instead. For small files, OTOH, buffering in RAM is somewhat easier and less error-prone.

Using QT how can I remove the first line in a text file without reading the entire file?

I'm manually logging events from my QT application into a text file.
I'm keeping track of how many lines I write into the text file and when I get over a certain amount I want to start removing the first line.
I shouldn't open and read the entire text file each time I want to remove the first line as the text file becomes large.
This is what I have so far:
if (file.open(QIODevice::Append)) {
QTextStream stream(&file);
stream << timeStamp+typeStamp+" "+message << endl;
stream.flush();
file.close();
LOG_COUNT++;
} else {
qWarning()<<"Utils::writeToLog - unable to write to log file";
}
if(LOG_COUNT > 5000){
LOG_COUNT--;
QFile inputFile(filename);
if (inputFile.open(QIODevice::ReadWrite))
{
QTextStream in(&inputFile);
QString line1 = in.readLine();
QString line2 = in.readLine();
qWarning()<<"LINE 1 "<<line1;
qWarning()<<"LINE 2 "<<line2;
//Replace line 1 & 2 with just line 2?
inputFile.close();
}
}
You can't cut something from the beginning of a file without creating a temp file.
So
either you read the whole file as a QString / QByteArray, chop the first line* and write it back
or
you open the file, find the offset of the end of the first line* and close the file, then open it again to write the remaining bytes to a temporary file, and rename it to the original.
[*] Either use QTextStream::readLine() or read bytes until you find a '\n' or '\r', depending on your platform.

Qt: prepend text to file

I wanted to write to a file and I did it, but it always writes to the last line. Is there a way to make it write to the first line? For example, given a file containing
apple
orange
and I want to add "banana"; I want the file to become:
banana
apple
orange
My current code is:
void Write (QString file)
{
QFile sfile(file);
if(!sfile.open(QFile::Append |QFile::Text))
{
return;
}
QTextStream out(&sfile);
out <<" "<<xscore<<" "<<oscore<<endl;
sfile.close();
}
How should I change this to insert text at the beginning of the file?
appending to a file will allways add at the end.
if you want to insert the first line, you can read the current file content (buffer), open it for writing and write your new content followed by the buffer
/edit:
a small example could look like this...
QFile sfile(file);
sfile.open(QFile::ReadOnly | QFile::Text);
QByteArray buffer = sfile.readAll();
sfile.close();
sfile.open(QFile::WriteOnly | QFile::Text);
QTextStream out(&sfile);
out <<" "<<xscore<<" "<<oscore<<endl;
out << buffer;

QT: Finding and replacing text in a file

I need to find and replace some text in the text file. I've googled and found out that easiest way is to read all data from file to QStringList, find and replace exact line with text and then write all data back to my file. Is it the shortest way? Can you provide some example, please.
UPD1 my solution is:
QString autorun;
QStringList listAuto;
QFile fileAutorun("./autorun.sh");
if(fileAutorun.open(QFile::ReadWrite |QFile::Text))
{
while(!fileAutorun.atEnd())
{
autorun += fileAutorun.readLine();
}
listAuto = autorun.split("\n");
int indexAPP = listAuto.indexOf(QRegExp("*APPLICATION*",Qt::CaseSensitive,QRegExp::Wildcard)); //searching for string with *APPLICATION* wildcard
listAuto[indexAPP] = *(app); //replacing string on QString* app
autorun = "";
autorun = listAuto.join("\n"); // from QStringList to QString
fileAutorun.seek(0);
QTextStream out(&fileAutorun);
out << autorun; //writing to the same file
fileAutorun.close();
}
else
{
qDebug() << "cannot read the file!";
}
If the required change, for example is to replace the 'ou' with the american 'o' such that
"colour behaviour flavour neighbour" becomes "color behavior flavor neighbor", you could do something like this: -
QByteArray fileData;
QFile file(fileName);
file.open(stderr, QIODevice::ReadWrite); // open for read and write
fileData = file.readAll(); // read all the data into the byte array
QString text(fileData); // add to text string for easy string replace
text.replace(QString("ou"), QString("o")); // replace text in string
file.seek(0); // go to the beginning of the file
file.write(text.toUtf8()); // write the new text back to the file
file.close(); // close the file handle.
I haven't compiled this, so there may be errors in the code, but it gives you the outline and general idea of what you can do.
To complete the accepted answer, here is a tested code. It is needed to use QByteArray instead of QString.
QFile file(fileName);
file.open(QIODevice::ReadWrite);
QByteArray text = file.readAll();
text.replace(QByteArray("ou"), QByteArray("o"));
file.seek(0);
file.write(text);
file.close();
I've being used regexp with batch-file and sed.exe (from gnuWin32, http://gnuwin32.sourceforge.net/). Its good enough for replace one-single text.
btw, there is not a simple regexp syntax there. let me know If you want to get some example of script.

Qt, QFile write on specific line

I've run into another problem in Qt, I can't seem to figure out how to write on a specific line on a text file with QFile. Instead, everything is erased written at the beginning.
So with the given information, how would I write to a specific line in QFile?
Here are two functions.
The first function searches a file, and then gets two variables. One that finds the next empty line, one that gets the current ID number.
Second function is supposed to write. But I've looked for documentation on what I need, I've googled it and tried many searches to no avail.
Function 1
QString fileName = "C:\\Users\\Gabe\\SeniorProj\\Students.txt";
QFile mFile(fileName);
QTextStream stream(&mFile);
QString line;
int x = 1; //this counts how many lines there are inside the text file
QString currentID;
if(!mFile.open(QFile::ReadOnly | QFile::Text)){
qDebug() << "Could not open file for reading";
return;
}
do {
line = stream.readLine();
QStringList parts = line.split(";", QString::KeepEmptyParts);
if (parts.length() == 3) {
QString id = parts[0];
QString firstName = parts[1];
QString lastName = parts[2];
x++; //this counts how many lines there are inside the text file
currentID = parts[0];//current ID number
}
}while (!line.isNull());
mFile.flush();
mFile.close();
Write(x, currentID); //calls function to operate on file
}
The function above reads the file, which looks like this.
1001;James;Bark
1002;Jeremy;Parker
1003;Seinfeld;Parker
1004;Sigfried;FonStein
1005;Rabbun;Hassan
1006;Jenniffer;Jones
1007;Agent;Smith
1008;Mister;Anderson
And the function gets two bits of information that I figured I might need. I'm not too familiar with QFile and searching, but I thought that I'd need these variables:
int x; //This becomes 9 at the end of the search.
QString currentID; //This becomes 1008 at the end of the search.
So I passed in those variables to the next function, at the end of function 1. Write(x, currentID);
Function 2
void StudentAddClass::Write(int currentLine, QString idNum){
QString fileName = "C:\\Users\\Gabe\\SeniorProj\\Students.txt";
QFile mFile(fileName);
QTextStream stream(&mFile);
QString line;
if(!mFile.open(QFile::WriteOnly | QFile::Text)){
qDebug() << "Could not open file for writing";
return;
}
QTextStream out(&mFile);
out << "HelloWorld";
}
I've left out any attempts at fixing the problem myself, all this function does is replace all the contents of the text file with "HelloWorld".
Does anyone know how to write on a specific line, or at least go to the end of the file and then write?
If the line you want to insert into the file is always the last line (as the function 1 suggest) you can try to open the file in append mode using QIODevice::Append in your Write method.
If you want to insert a line in the middle of the file, I suppose an easy way is to use a temp file (or, if it is possible, to load the lines into a QList, insert the line and write the list back to the file)
QString fileName = "student.txt";
QFile mFile(fileName);
if(!mFile.open(QFile::Append | QFile::Text)){
qDebug() << "Could not open file for writing";
return 0;
}
QTextStream out(&mFile);
out << "The magic number is: " << 4 << "\n";
mFile.close();
The above code snippet will append the text "The magic number is: 4" , at the end of the file.