I would like to append entries in a simple csv file at the second line. The first line contains my column headers and the newest entry has to be on top.
My thought is to read in the first line until the '\n', then move to the next line and write there, but i don't know if that is the most efficient solution. Can someone provide an example?
Since you have stated in the comments that this file will not be very large I would suggest you read in the header into some sort of container. Then insert after the header the newest data that needs to be inserted into the file. Then read in the rest of the file. After you do that then you can write the contents of the container back into the file. Here is a simple demonstration:
std::ifstream fin("somefilename");
std::vector<std::string> file;
file.reserve(30); // grow the capacity to save on allocations
std::string reader;
std::string new_data = "some new data";
getline(fin, reader);
file.push_back(reader); //add header
file.push_back(new_data); // add new line
while(getline(fin, reader)) // get rest of file
file.push_back(reader);
std::ofstream fout("somefilename");
for (const auto & e : file)
fout << e << "\n";
Related
Is it possible to edit text in a file using cpp code. Already there is related question on it, but it doesn't solve my problem. Kindly help me out.
I have given a rough code line on this.
seek() through the file and try to replace the contents with new string from that point till the end of line.
I need the "hello" string be placed and must be the end of line.
like if we have new.txt as
ABCDEFGHIJKLMNOPQRST
If I want the file content to be changed as
ABCDEHELLO
I am getting the file content as
ABCDHELLOJKLMNOPQRST
fstream file("new.txt",fstream::in|fstream::out);
file.open();
while(getline(file,str))
{
if(value==strstr())
{
file.seekp(pos);
str.erase(pos,len);//len specifies the value till end of str
str.replace(pos,6,"hello");
char *d=new char[str.length()+1];
strcpy(d,str.c_str());
file.write(d,strlen(d));
delete [] d;
}
}
If I could copy the file contents to the string, manipulate it, then copy to the new file then it is possible.
Is it possible to change the contents in the same file. If so kindly help me out, I am struck in this. If the replacing string is longer than the one actually existing then this works, but if the replacing string is smaller than the one which is actually existing then I am unable to do.
if you case is only one line in the file you can easily separate the I/O process in two stages. Read the file and get the position of the text. then close the file and reopened as out then write the string you want. Note that this will work if you have one line in the file
check the following code
std::string value = "GFGHHFGHH";
std::string str;
std::fstream file("new.txt", std::ios::in);
std::size_t found;
while (file >> str)
{
found = str.find(value);
if (found != std::string::npos)
{
str.erase(value.length() );
str.replace(found, 6, "hello");
}
}
file.close();
file.open("new.txt", std::ios::out);
file << str;
file.close();
You can do it using system call for sed:
string s="sed -i s/hey/ho/g file0102.txt";
system(s.c_str());
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");
}
I am new to file-handling...
I am writing a program that saves data in text-files in the following format:
3740541120991
Syed Waqas Ali
Rawalpindi
Lahore
12-12-2012
23:24
1
1
(Sorry for the bad alignment, it's NOT a part of the program)
Now I'm writing a delete function for the program that would delete a record.
So far this is my code:
void masterSystem::cancelReservation()
{
string line;
string searchfor = "3740541120991";
int i=0;
ifstream myfile("records.txt");
while (getline(myfile, line))
{
cout << line << endl;
if (line==searchfor)
{
// DELETE THIS + THE NEXT 8 LINES
}
}
}
I've done a bit of research and have found out that there is no easy way to access the line of a text file so we have to create another text file.
But the problem arises that how do I COPY the records/data before the record being deleted into the NEW text file?
Open the input file; read one line at a time from the input file. If you decide to want to keep that line, write it to the output file. On the other hand, if you want to 'delete' that line, don't write it to the output file.
You could have a record per line and make even more easy for example:
3740541120991|Syed Waqas Ali|Rawalpindi|Lahore|12-12-2012|23:24|1|1
and the | character saparating each field. This is a well known technic knows as CSV (Comma separated Values)
This way you don't have to worry about reading consecutive lines for erase a record and add a record access the file only once.
So your code becoms into:
void masterSystem::cancelReservation()
{
string line;
string searchfor = "3740541120991";
ifstream myfile("records.txt");
while (getline(myfile, line))
{
// Here each line is a record
// You only hace to decide if you will copy
// this line to the ouput file or not.
}
}
Don't think only about removing a record, there are others operations you will need to do against this file save a new record, read into memory and search.
Think a moment about search, and having your current desing in mind, try to answer this: How many reservations exists for date 12-12-2012 and past 12:00 AM?
In your code you have to access the file 8 times per record even if the other data is irrelevant to the question. But, if you have each record in a line you only have to access file 1 time per record.
With a few reservations the diference is near 0, but it grows exponentially (n^8).
I want to read and write compressed file with my C++ script. For this purpose, I use the gzstream lib. It works fine with a very simple example like this :
string inFile="/path/inputfile.gz";
igzstream inputfile;
ogzstream outputfile("/path/outputfile.gz");
inputfile.open(inFile.c_str());
// Writing from input file to output file
string line;
while(getline(inputfile, line)) {
outputfile << line << endl;
}
But in my C++ script, things are more complicated and my output files are created within a dynamic vector.
For UNcompressed files, this way worked very fine :
string inFile="/path/uncompressedInputFile.ext";
ifstream inputfile;
vector <ofstream *> outfiles(1);
string outputfile="/path/uncompressedOutputFile.ext";
outfiles[1] = new ofstream(outputfile.c_str());
inputfile.open(inFile.c_str());
string line;
while(getline(inputfile, line)) {
*outfiles[1] << line << endl;
}
Now with compressed file, this way produces me corrupted files :
string inFile="/path/compressedFile.gz";
igzstream inputfile;
vector <ogzstream *> outfiles(1);
string outputfile="/path/compressedOutputFile.gz";
outfiles[1] = new ogzstream(outputfile.c_str());
inputfile.open(inFile.c_str());
string line;
while(getline(inputfile, line)) {
*outfiles[1] << line << endl;
}
I got a "compressedOutputFile.gz" in my path, not empty, but when trying to uncompressed it I got "unexpected end of file" which, I guess, means the file is corrupted....
What's wrong with it ? Can anyone please help me ?! :)
In the simple example, the GZip file is closed automatically when the ofstream is destroyed, which flushes its remaining buffer to disk.
In the dynamic example, you're not closing because the object is being created on the heap. In both cases, this could result in the loss of data at the end of the file, depending on the format. Since GZip is compressed, it's more likely to lose more relevant data, resulting in a more obvious failure.
The best solution is to create a vector<unique_ptr<ogzstream> >, which cause it to automatically destroy streams when they go out of scope. The less optimal solution is to remember to manually delete each pointer prior to exiting the function.
Edit: And as a quick note, as pointed out by #doctorlove in the original comments, you need to use the correct index, otherwise you're causing other issues.
I have this code that is supposed to transfer a file into another file in reverse order, line by line. However it does not work. Maybe I forgot to add something:
while(cnvFile.good()) {
getline(cnvFile, cnvPerLine);
reverseFile << cnvPerLine;
reverseFile.seekp(0, ios::beg);
}
When you seek to the beginning and try to write, you're not inserting data, you're overwriting data. A simple (albeit probably far from optimal) solution would be something like:
std::string reversedContents
while (getline(inFile, line)) {
// This actually *appends* to the beginning, not overwriting
reversedContents = line + "\n" + reversedContents; // manually add line breaks back in
}
// now write reversedContents to a file...