QT: Finding and replacing text in a file - c++

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.

Related

How to read in a file word by word in QT?

As you can probably tell I am new to QT and I am attempting to import my console app's src code and headers to qt to build a GUI. I am stuck on one particular function which is supposed to load a file and read it in word by word. I know how to do this in C++, but in QT I have been at it for hours and I am not quite sure how to go about it. Along with reading in the file, I have to insert a string (or in this case type T) by using my own personal insert function (irrelevant to the question).
As of right now i am doing which I know is not working for conversion reasons etc:
template <typename T>
bool HashTable<T>::load(const char* filename)
{
QString word;
QFile inputFile(filename);
QTextStream fin(filename);
// std::ifstream iss;
QString line;
// iss.clear();
// iss.open(filename);
while (fin >> word)
{
insert(word);
}
fin.close();
return true;
}
QTextStream does (to my knowledge) not support word-by-word reading of files, it only support reading a certain number of characters (via read(qint64 maxlen)), reading entire lines (via readLine(qint64 maxlen = 0)) or a combination of the above. An example on how to do this is described in this answer.
What you might do - in order to get a list of words - is reading line-by-line, and splitting each read line with QString's split() function, using space as separator.
template <typename T>
bool HashTable<T>::load(const char* filename)
{
QFile inputFile(filename);
if(!inputFile.open(QIODevice::ReadOnly)) {
QMessageBox::information(0, "error", inputFile.errorString());
}
QTextStream fin(&inputFile);
while(!fin.atEnd()) {
QString line = in.readLine();
QStringList words = line.split(" ");
foreach(QString word, words){
insert(word);
}
}
filename.close();
return true;
}
You have to first open your file for reading. Then textstream should be read line by line. In above code I read a line and then split it to words using space (" ") as the token. Then you can read words from the QStringlist.

How to write text to a text file only if not already written

I would like to add text to a text file only if the text doesn't already exist in the text file. My implementation below adds text even if it already exists. How can I fix my implementation to only add new non-existent items?
My implementation so far:
WriteToFile::WriteToFile(QString data)
{
path += "C:/Data.txt";
QFile file(path);
if ( file.open(QFile::Append) )
{
QTextStream in (&file);
QString line;
do {
line = in.readAll();
qDebug() << in.readLine();
if (!line.contains(data)) {
QTextStream stream( &file );
data += "\r\n";
stream << data << endl;
}
} while (!line.isNull());
}
}
You will either have to:
parse the entire file and extract all paths from it or
keep track of all paths written to a file to avoid parsing it again and again
From there is it simple, just create a QSet<QString> writtenSoFar, and for every path, check if the set contains it, if so skip writing, if not, write it and append it to the set. In the first case, you will have to write the parsed paths into the set just to make a single check, wildly inefficient, just like the parsing itself. So better keep track of the paths as you go.
The set is important to give you good lookup performance. It is quite fast, since it is hash based, it is essentially a value-less QHash.

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;

Reading a txt file using QTextStream 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?

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.