QT, Write in new line in a file - c++

I have written a code to read from line_Edit in GUI, and write in a file. The code reads the text from line edit and writes the same in the file, but they are printed continuously without any spaces, I want to print the texts written in the line edit in different lines. The file has written text, just want to replace first word of each line by the user entered words.
Code to write in the file:
void MainWindow::on_write_btn_clicked(){
QString str, str2, lin;
str = ui->lineEdit->text();
str2 = ui->lineEdit2->text();
QFile file1("sample.txt");
if(file1.open(QIODevice::ReadWrite | QIODevice::Text)){
QTextStream out(&file1);
out << str;
lin = out.readLine();
out << str2;
file1.seek(30);
file1.close();
}
else
return;
}
File in which we want to write:

If you want the next string to be in a new line in the file you should add the new line character(s) to the stream \n.
Referring to your code you should put:
out << str << '\n' << str2;
which would make the contents of str and str2 appear in consecutive lines.
Instead of the above you could also use the endl manipulator from QTextStream:
out << str << endl << str2;
For this to work properly you need to be opening the file with QIODevice::Text and assure that the endl you are specifying actually comes from QTextStream (not std)
Also note that since you probably only want to write your file there is no need in opening it with ReadWrite option, WriteOnly should be enough.
EDIT according to further details:
To substitute first word from each line of the file you could do the following. Open two files, one which will be read and the second to write the modified data. After iterating though all the lines close the files, remove the original one and rename the output file to replace the original one. Sample implementation:
QFile fileIn("textIn.txt"), fileOut("textOut.txt");
fileIn.open(QFile::ReadOnly); // check result
fileOut.open(QFile::WriteOnly); // check result
QTextStream streamIn(&fileIn), streamOut(&fileOut);
const QChar delimeter = ' ';
while (!streamIn.atEnd())
{
QStringList list = streamIn.readLine().split(delimeter);
if (list.size() > 0) // in case of empty line
list[0] = "substitutedText"; // here put the text you want to set
streamOut << list.join(delimeter) << "\r\n"; // or endl
}
fileIn.close();
fileOut.close();
fileIn.remove(); // check result
fileOut.rename(QFileInfo(fileIn).absoluteFilePath()); // check result
Of course you could try doing the replacement on the original file opened with ReadWrite modifier and setting proper position inside the stream using seek. Although it could get tricky due to different lengths of the read and written data.

Related

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 QFile delete line from CSV File

I have a CSV file and I want to delete a specific line in it. The way I want to do this is by reading the file line by line and checking if the first element of the line is equal to a variable. If it's equal => remove the line.
// get the project name from the combo box
QVariant projectName = ui->projectCombo->currentText();
QFile projectFile(CSV File);
// checks if file is valid and can open
if(!projectFile.open(QIODevice::ReadOnly)) {
cout << "Error: can't copen file" << endl;
} else {
cout << "File open successfully" << endl;
}
QTextStream in(&projectFile);
while(!in.atEnd()) {
QString line = in.readLine();
// Get the first element from line
QString firstElement = line.split(',').first();
// Check if firstElement is equal to the variable projectName
if (firstElement == projectName.toString()) {
// Delete current line
}
}
I'm doing this because I want to update specific data on that line. I know Qt, let alone c++, can't do this. So I thought I get the line from the file, put it in a data structure, delete it from the file, edit the desired data inside the data structure and then append to file the changed data from the data structure
If you want to delete according to the line number you can use this
m_File.close();
QString qCommand = "sed -i 2d "+fileName;
string command = qCommand.toUtf8().constData();
system(command.c_str());
m_File.open(FileName.c_str(), ios::out|ios::app);
Make a function like this, and pass the necessary parameters.
After you can even append to the same file, as its opened inside the same function

How to extract specific substring from getline function in C++?

I'm fairly new to C++ so please forgive me if my terminology or methodology isn't correct.
I'm trying to write a simple program that:
Opens two input files ("infileicd" and "infilesel").
Opens a single output file "list.txt".
Compares "infilesel" to "infileicd" line by line.
If a line from "infilesel" is found in "infileicd", it writes that line from "infileicd" to "list.txt", effectively making a separate log file.
I am using the getline() function to do this but have run into trouble when trying to compare each file line. I think it might be easier if I could use only the substring of interest to use as a comparison.
The problem is that there are multiple words within the entire getline string and I am only really interested in the second one. Here are two examples:
"1529 nic1_mau_op_mode_3 "8664afm007-01" "1" OUTPUT 1 0 LOGICAL 4 4136"
"1523 pilot_mfd_only_sel "8664afm003-02" "1" OUTPUT 1 0 LOGICAL 4 4112"
"nic1_mau_op_mode_3" and "pilot_mfd_only_sel" are the only substrings of interest.
It would make it a lot easier if I could only use that second substring to compare but I don't know how to extract it specifically from the getline() function. I haven't found anything suggesting it is impossible to do this, but if it is impossible, what would be an alternative method for extracting that substring?
This is a personal project so I'm under no time contstraints.
Any assistance is greatly apprecated in advance. Here is my code (so far):
int main()
{
//Open the file to write the selected variables to.
ofstream writer("list.txt");
//Open the selected variabels file to be read.
ifstream infilesel;
infilesel.open("varsel.txt");
//Open the icd file to be read.
ifstream infileicd;
infileicd.open("aic_fdk_host.txt");
//Check icd file for errors.
if (infileicd.fail()){
cerr << "Error opening icd.\n" << endl;
return 1;
}
else {
cout << "The icd file has been opened.\n";
}
//Check selected variables file for errors.
if (infilesel.fail()){
cerr << "Error opening selection file.\n" << endl;
return 1;
}
else {
cout << "The selection file has been opened.\n";
}
//Read each infile and copy contents of icd file to the list file.
string namesel;
string nameicd;
while(!infileicd.eof()){
getline(infileicd, nameicd);
getline(infilesel, namesel);
if (nameicd != namesel){ //This is where I would like to extract and compare the two specific strings
infileicd; //Skip to next line if not the same
} else {
writer << nameicd << namesel << endl;
}
}
writer.close();
infilesel.close();
infileicd.close();
return 0;
}
So, based on what we discussed in the comments, you just need to toss the stuff you don't want. So try this:
string namesel;
string nameicd;
string junk;
while(!infileicd.eof()){
// Get the first section, which we'll ignore
getline(infileicd, junk, ' ');
getline(infilesel, junk, ' ');
// Get the real data
getline(infileicd, nameicd, ' ');
getline(infilesel, namesel, ' ');
// Get the rest of the line, which we'll ignore
getline(infileicd, junk);
getline(infilesel, junk);
Basically, getline takes a delimiter, which by default is a newline. By setting it as a space the first time, you get rid of the first junk section, using the same method, you get the part you want, and then the final portion goes to the end of the line, also ignoring it.

C++ ofstream : Always write onthe 1st line

I would like to know how could I write always to the first line of a file.
I have numbers to share via a text file to another soft, and I want to write those numbers periodically on the first line.
Thanks.
eo
If you want to completely rewrite the file, discarding it's contents then simply use trunc mode. However, if there is any other content that you want to preserve then the easiest way would be to read the file into memory, change the first line and write everything back. I think it wouldn't be possible to change the first line directly unless you are overwriting the same amount of characters.
Look at this two functions:
ostream& seekp ( streampos pos );
ostream& seekp ( streamoff off, ios_bas:seekdir dir );
maybe this solves your problem
ofstream out("foo.txt");
out << "foo";
out << "\r" << "bar";
this will leave a file with only bar in it.
2nd method:
if the file only contains one line you could open it with ofstream::trunc and close it after each write
If the file is not massive then you could write a new new file copying across each line except for the custom first line. Then afterwards replace the original.
void ReplaceFirstLine(string filename)
{
ifstream infile;
ofstream outfile;
infile.open(filename.c_str(), ios_base::in);
outfile.open("tempname.txt", ios_base::out);
bool first = true;
string s;
while (getline(infile, s, '\n'))
{
if (first)
outfile << "my new first line\n";
else
outfile << s << endl;
first = false;
}
infile.close();
outfile.close();
::CopyFileA("tempname.txt", filename.c_str(), FALSE); // or Linux equivalent
}

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.