Erase empty lines from a text file in C++ - c++

I have a text file, which may contain some empty lines. I want to open this file and look for the empty lines. If an empty line exists then, I want to delete that line. I do not want to create a temporary file for this purpose. I want to edit the same file and close it afterwards.
I have already seen a couple of posts about similar problem but none of them worked for me.
void DeleteEmptyLines(const string& FilePath)
{
//EXISTING File
std::fstream FileStream;
std::string CurrentReadLine;
if (doesFileExist(FilePath))
{
FileStream.open(FilePath, std::fstream::in | std::fstream::out | std::fstream::app);
//Read all the lines till the end of the file
while(getline(FileStream, CurrentReadLine))
{
//Check if the line is empty
if(CurrentReadLine.empty())
{
cout<<"Empty line found"<<endl;
//DELETE THIS EMPTY LINE
}
}
FileStream.clear();
FileStream.close();
}
// else --->> do nothing
}
Current File (MyFile.txt):
Line1
Line2
Line3
What I need (MyFile.txt):
Line1
Line2
Line3
PS: I am using VS2010 on windows machine.

Simple solution. Reads file into a string skipping empty lines, then overwrites the file with the contents of the string.
void DeleteEmptyLines(const std::string &FilePath)
{
std::ifstream in(FilePath);
std::string line, text;
while (std::getline(in, line))
if !(line.empty() || line.find_first_not_of(' ') == std::string::npos)
text += line + "\n"
in.close();
std::ofstream out(FilePath);
out << text;
}
EDIT: #skm The new answer you posted does not erase lines with empty spaces, as you stated.
To fix this use this condition to make sure a line is not "empty":
!(CurrentReadLine.empty() || CurrentReadLine.find_first_not_of(' ') == std::string::npos)

You can't do it in all currently used filesystems, because data is stored successively. So do 'delete' some bytes from file you have to move all subsequent bytes at that amount of bytes. And you can't open file for reading and at that moment rewrite it from beginning.
So you have 3 options:
Read all file into memory and then rewrite lines to the original
file skipping empty lines.
Read file line by line, save only
non-empty lines into memory, and then write then down to the same file.
Use temporary file, which is actually a good choice because you
don't have to have a lot of RAM and file moving operation is
low-cost at most filesystems (if source and destination are at the
same partition).

I have modified my function as following.
void DeleteEmptyLines(const string& FilePath)
{
std::string BufferString = "";
//File
std::fstream FileStream;
std::string CurrentReadLine;
if (doesFileExist(FilePath))
{
FileStream.open(FilePath, std::fstream::in); //open the file in Input mode
//Read all the lines till the end of the file
while(getline(FileStream, CurrentReadLine))
{
//Check if the line is empty
if(!CurrentReadLine.empty())
BufferString = BufferString + CurrentReadLine + "\n";
}
if(DEBUG) cout<<BufferString<<endl;
FileStream.close();
FileStream.open(FilePath, std::fstream::out); //open file in Output mode. This line will delete all data inside the file.
FileStream << BufferString;
FileStream.close();
}
// else --->> do nothing
}
This function does the following steps:
Open the file in input mode
Read all the lines which are not empty
Closes the file
Open the file again in Output mode (deletes all the data inside file)
Put the string into the file
Closes the file.

Related

C++ Write line from text file to new file. Copies previews line not current line

I have a loop the reads through my text file and when it finds a match for my condition I want it to print that line to a new text file. My code works it is just printing the preview line not the current, and it keeps over writing onto the first line of the text file.
void FileManager::copyLine(std::string newLine)
{
line1 = newLine;
std::ofstream outFile("temp.txt");
outFile << line1 << std::endl;
outFile.close();
}
if (p1.getPos() == "WR")
{
if (line2.getPosWR1().empty())
{
line2.setWR1_Pos(p1.getPos());
line2.setWR1_Name(p1.getName());
line2.setWR1_Salary(p1.getSal());
line2.setWR1_Projection(p1.getProj());
file1.copyLine(line);
wr1++;
}
else if (!line2.getPosWR1().empty() && line2.getPosWR2().empty())
{
line2.setWR2_Pos(p1.getPos());
line2.setWR2_Name(p1.getName());
line2.setWR2_Salary(p1.getSal());
line2.setWR2_Projection(p1.getProj());
file1.copyLine(line);
wr2++;
}
New to stack overflow :D but I found the my answer this is the change I made so simple!
std::ofstream outFile("temp.txt", std::ios::app);
I just had to add the ios::app. to append to the end of the file.

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.

Replace line in txt file c++

I just wondering cause i have a text file containing STATUS:USERID:PASSWORD in accounts.txt
example it would look like this:
OPEN:bob:askmehere:
OPEN:john:askmethere:
LOCK:rob:robmypurse:
i have a user input in my main as such user can login 3x else status will change from OPEN to LOCK
example after 3 tries of john
before:
OPEN:bob:askmehere:
OPEN:john:askmethere:
LOCK:rob:robmypurse:
after:
OPEN:bob:askmehere:
LOCK:john:askmethere:
LOCK:rob:robmypurse:
what i have done is:
void lockUser(Accounts& in){
// Accounts class consist 3 attributes (string userid, string pass, status)
ofstream oFile;
fstream iFile;
string openFile="accounts.txt";
string status, userid, garbage;
Accounts toupdate;
oFile.open(openFile);
iFile.open(openFile);
while(!iFile.eof()){
getline(iFile, status, ':');
getline(iFile, userid, ':');
getline(iFile, garbage, '\n');
if(userid == in.getUserId()){
toupdate.setUserId(in.getuserId());
toupdate.setPassword(in.getPassword());
toupdate.setStatus("LOCK");
break;
}
//here i should update the account.txt how do i do that?
ofile.open(openFile);
ofile<<toupdate.getStatus()<<":"<<toupdate.getUserId()":"<<toupdate.getPassword()<<":"<<endl;
}
There are two common ways to replace or otherwise modify a file. The first and the "classic" way is to read the file, line by line, check for the line(s) that needs to be modified, and write to a temporary file. When you reach the end of the input file you close it, and rename the temporary file as the input file.
The other common way is when the file is relatively small, or you have a lot of memory, is to read it all into memory, do the modification needed, and then write out the contents of the memory to the file. How to store it in memory can be different, like a vector containing lines from the file, or a vector (or other buffer) containing all characters from the file without separation.
Your implementation is flawed because you open the output file (which is the same as the input file) inside the loop. The first problem with this is that the operating system may not allow you to open a file for writing if you already have it open for reading, and as you don't check for failure from opening the files you will not know about this. Another problem is if the operating system allows it, then your call to open will truncate the existing file, causing you to loose all but the very first line.
Simple pseudo-ish code to explain
std::ifstream input_file("your_file");
std::vector<std::string> lines;
std::string input;
while (std::getline(input_file, input))
lines.push_back(input);
for (auto& line : lines)
{
if (line_needs_to_be_modified(line))
modify_line_as_needed(line);
}
input_file.close();
std::ofstream output_file("your_file");
for (auto const& line : lines)
output_file << line << '\n';
Use ReadLine and find the line you wanna replace, and use replace to replace the thing you wanna replace. For example write:
string Example = "Text to find";
openFile="C:\\accounts.txt"; // the path of the file
ReadFile(openFile, Example);
OR
#include <fstream>
#include <iostream>
#include <string>
int main() {
ifstream openFile;
string ExampleText = BOB;
openFile("accounts.txt");
openFile >> ExampleText;
openFile.replace(Example, "Hello");
}

Cant open file using c_str() in linux

On Windows, I have no problems opening the file from string. On Linux (where it needs to work) I can't open the file.
string name;
//open 1st file, with the next file name - this works
fstream file( "data.dat", ios::in);
if(file.good()){
getline(file, name);
//some code here
file.close();
}else{
return 1;
}
// this here does not work
fstream file1(name.c_str() , ios::in);
if(file1.good()){
//some code here
file1.close();
}else{
cout<<"can't open file"<<endl;
return 1;
}
If instead name.c_str() I write the file name directly it works, but every try on getting the name from the file ended with the file not opening.
I've tried creating const char* from name, doesn't work too.
The file probably has Windows-style line endings. Either sanitise the file, or check for and remove any carriage-return character, \r, at the end of each line.

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
}