I'm working on a program, that needs to load data from a text file upon starting and save data to THE SAME text file upon exit. I have the load working, and i have the save working, but for some reason I cant seem to have them both work within the same program.
This doesnt work...
ifstream loadfile("test.txt");
ofstream savefile("test.txt");
void load()
{
string name;
while(!loadfile.eof())
{
getline(loadfile,name);
cout<<"name " << name<<"\n";
}
}
void save(User &name)
{
savefile << name.getName() << endl;
}
Neither does this...
fstream file("test.txt");
void load()
{
string name;
while(! file.eof())
{
getline(file,name);
cout<<"name " << name<<"\n";
}
}
void save(User &name)
{
file << name.getName() << endl;
}
The thing is, I can save a list of names, which works fine... but as soon as i start the program, all the names from the list delete from the text file.
Also, I know that getline() gets the data from the text file as a string type, but how would i convert that to something like an int.
Thanks
Your files are being opened globally and never closed. Try:
void load()
{
ifstream loadfile("test.txt");
string name;
while(!loadfile.eof())
{
getline(loadfile,name);
cout<<"name " << name<<"\n";
}
}
void save(User &name)
{
ofstream savefile("test.txt");
savefile << name.getName() << endl;
}
ofstream savefile("test.txt");
is equivalent to:
ofstream savefile;
savefile.open("test.txt", ios::out|ios::trunc);
That is, you're truncating the file as you open it. So, move the initialization of savefile to happen after you're done with your load call (I'd suggest doing it as late as possible, because if you crash after that initialization and before you're done saving, the save file is corrupted -- normally one writes to a different file and only does the rename at the very end when everything is safe on disk).
In your first sample, you may be running afoul of OS file locking, preventing you from opening the same file for both read and write. Remember to always check for failure when opening a file.
In the second sample, you don't rewind the file pointer. Use seekg to reset the stream pointer before trying to read. Keep in mind that although there's a seperate seekg and seekp, in practice they may refer to the same pointer, so it's always best to seek before switching between read and write.
void load(){
ifstream loadfile("test.txt");
string name;
while(!loadfile.eof())
{
getline(loadfile,name);
cout<<"name " << name<<"\n";
}
loadfile.close(); // Call close() to free up resources again
}
void save(User &name)
{
ofstream savefile("test.txt");
savefile << name.getName() << endl;
savefile.close(); // Call close() to free up resources again
}
From Cplusplus I/O:
"Once this member function is called, the stream object can be used to open another file, and the file is available again to be opened by other processes."
Related
I opened a file both read and write mode
using the following statement
file.open(fileName, ios::in | ios::out | ios::trunc);
my main purpose for opening the file in both mode is, read and write the file at the same time.
But In my code scenario,
when I am reading the file after writing it, the ouput showing blank that means,
it is not saving my writing contents because I am not closing it.
And I want to close the file after finishing both write and read the operation
I found a solution in Stack Overflow,
to use flush() function to save the file without closing
file.flush();
but, the problem is it's not working for my case
So, how can I save c++ fstream file without closing?
Here's my full code for better understanding
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main(int argc, char const *argv[])
{
string fileName = "text.txt";
fstream file;
file.open(fileName, ios::in | ios::out | ios::trunc);
if (file.is_open())
{
file << "I am a Programmer" << endl;
file << "I love to play" << endl;
file << "I love to work game and software development" << endl;
file << "My id is: " << 1510176113 << endl;
file.flush(); // not working
}
else
{
cout << "can not open the file: " << fileName << endl;
}
if (file.is_open())
{
string line;
while(file)
{
getline(file, line);
cout << line << endl;
}
}
else
{
cout << "can not read file: " << fileName << endl;
}
file.close();
return 0;
}
Actually, if you want to save any file immediately without closing the file, then you can simply use
file.flush();
But if you are want to read the file without closing just after writing it, you can simply use
file.seekg(0);
actually seekg() function resets the file pointer at the beginning, for this, it is not mandatory to save the file. so, this has nothing to with flush() function
but you can do both if you want to
Before reading from that file you need to make sure to place the pointer to that file to the beginning of the file. After writing to the file it'll point to the end. Therefore you won't be able to read anything.
You need to use file.seekg(0); somewhere after the file.flush() but before starting to read to place the file pointer to the very beginning.
Update
This should work without the flush. However this will depend on the implementation of the std library. Although I'd consider this as bug if it doesn't work without calling flush() imho it does not hurt to call it explicitly.
I am a fairly novice programmer, taking a few courses in my second year of highschool, and I have ran into a few problems. So let's get on with it.
Long story short, I have learnt how to create files like:
#include <iostream>
#include <fstream>
using namespace std;
int main(){
string Test;
ofstream file;
file.open("Cookies.txt");
if(file.is_open()){
file << "I have cookies! :3" << endl;
file.close();
}
else{
cout << "Error. No file has been created." << endl;
}
ifstream cookies;
cookies.open("Cookies.txt");
if(cookies.is_open()){
cout << cookies.rdbuf();
}
return 0;
}
But my question now is, how do I like "use" what is in this file? Like if I want to save variables, or import the "I have cookies! :3" to a string variable in the main program. Because it seems reasonable that it should be possible, I have just not found out how to yet.
Also, how do I delete files that I have created? Because something like
file.delete("Cookies.txt"); does not work at all.
Thank you for your answers in advance.
Best regards, Staggen.
You can read from a file in a similar manner to writing to it, using an ifstream (input filestream) instead of an ofstream (output filestream), and using the >> operator to read into variables. It does default to reading a single value at a time, and for strings that translates into "words":
So:
if (cookies.is_open())
{
std::string word;
while (cookies >> word) // read from the filestream into "line"
{
std::cout << "Read a word: " << line << std::endl;
}
}
This is a fairly good method for reading different data types.
To read the entire line, you can use std::getline() with the newline character as the delimiter:
if (cookies.is_open())
{
std::string line;
while (std::getline(cookies, line, '\n'))
{
std::cout << "Read a line: " << line << std::endl;
}
}
Deleting a file is an OS-level activity unrelated to reading/writing to files. The <cstdio> header includes std::remove() which will delete files.
#anderas is right; you should go through a tutorial on file I/O in order to learn or solidify the basics.
i am new to this site , and this my first question !
i have a question about fstream function .
fstream f("new.dat",ios::out|ios::in);
fstream is for both input and output , so when we use it like this , and there is a new.dat file before it will output and input both . but it is strange , when i do that , it will output data correctly , but it is unable to input .
i found out if you close it , and reopen it , it will input . why it is like that??
int main()
{
fstream writeFile("newFile.dat", ios::out|ios::in);
char i[3];
char u[3]="HI";
if (!writeFile)
{
cerr << "error" << endl;
}
writeFile << u <<endl;
writeFile >> i;
cout << i << endl;
}
this is my full code , and result is an empty line.
The fstream object has a position in its output file, and since you opened it just for output and input without any position or writing modifiers, that position is at the end of the file. When you output i to the file, writeFile writes i to the file, and then moves its position past i so when you ask it to write more, you don't overwrite i.
You can reset the position to the start of the file with a call to writeFile.seekg(0), which places that internal position at the 0 position in the file (at the start).
If you're curious about stream manipulation, I'd suggest a look at cppreference.com and specifically its documentation on c++'s input and output libraries here.
Couple things going on here:
You can't open a file for reading if it doesn't exist, this includes a file you want to read and write. No file, no open.
Once you manage to open a file, the stream keeps track of where it is in the file. As you read or write, obviously the location moves.
There is only one location marker in the stream, so you can read to where you want to write, then write. Unfortunately this means any further reading will pick up after the write. If that's not what you want, get and store the current location (with tellg) before writing, and seek (with seekg) to the stored location after writing.
This has some problems such as what if the block of data you wish to insert is longer or shorter than the block of data you want to overwrite? The simple solution to this problem is read into buffer, edit buffer, write buffer back to file.
When you open a file and start writing into it, you overwrite whatever was in the file. If you want to add to a file, open with ios::app. This sets the stream's location to the end of the file. I am unaware of any sort of insert that pushes existing data along as you write in new data.
Some simple file handling example code
#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;
int main()
{
fstream f1("filename", ios::out);
if (f1.is_open())
{
if (f1 << "Hi")
{
cout << "wrote"<<endl;
}
f1.close();
}
fstream f2("filename", ios::out|ios::app);
if (f2.is_open())
{
if (f2 << " there!")
{
cout << "appended"<<endl;
}
f2.close();
}
fstream f3("filename", ios::in);
if (f3.is_open())
{
cout << f3.rdbuf()<< endl;
f3.close();
}
fstream f4("filename", ios::in|ios::out);
if (f4.is_open())
{
f4.seekg(3);
if (f4 << "Fred!")
{
cout << "overwrote"<<endl;
}
f4.close();
}
fstream f5("filename", ios::in);
if (f5.is_open())
{
cout << f5.rdbuf()<< endl;
f5.close();
}
// note the extra ! on the end left over from Hi there! I do not know how
// to get rid of this. I have always just done stuff like this to get around it.
fstream f6("filename", ios::in);
stringstream s1;
string token;
f6 >> token;
s1 << token << " Tim!";
f6.close();
fstream f7("filename", ios::out);
f7 << s1.rdbuf();
f7.close();
// and then moved temp over filename.
fstream f8("filename", ios::in);
cout << f8.rdbuf()<< endl;
f8.close();
}
This question already has answers here:
Reading and writing to the same file using the same fstream
(2 answers)
Closed 9 years ago.
I have a pretty simple code:
void LookupName( string tname ){ //Checks for name in records.txt and enters it if it does not exist
//Variables
string fname; //Used to store the name
string throwaway; //Used to dispose of extra data
bool found = false; //Used to track if a name is found in the file
//objects
fstream file ( STATS_FILE ); //Open the file
if (file.is_open()) {
while ( !file.eof() ) {
getline (file, fname, DELIM); //Fill name
getline (file, throwaway, '\n'); //throw away rest of line
cout << "Found: " << fname << " tname: " << tname << '\n';
Pause();
if ( fname == tname ) { //Otherwise, continue
cout << "Found: " << fname << " tname: " << tname << '\n';
Pause();
found = true;
}
}
if ( found == false ) { //if the name is not found
//Reopen the file so that we can write to it
file.close();
file.open( STATS_FILE, fstream::in | fstream::out | fstream::app );
cout << "Not found" <<endl;
Pause();
file << tname << ",0,0\n"; //Add it to the file with 0 wins and losses
}
//Cleanup
file.close();
}
}
This works, but if you notice at the bottom when I check to see if the name is found, I have to close and re-open the file.
The follow will not work for some reason:
void LookupName( string tname ){ //Checks for name in records.txt and enters it if it does not exist
//Variables
string fname; //Used to store the name
string throwaway; //Used to dispose of extra data
bool found = false; //Used to track if a name is found in the file
//objects
fstream file ( STATS_FILE, fstream::in | fstream::out | fstream::app ); //Open the file
if (file.is_open()) {
while ( !file.eof() ) {
getline (file, fname, DELIM); //Fill name
getline (file, throwaway, '\n'); //throw away rest of line
cout << "Found: " << fname << " tname: " << tname << '\n';
Pause();
if ( fname == tname ) { //Otherwise, continue
cout << "Found: " << fname << " tname: " << tname << '\n';
Pause();
found = true;
}
}
if ( found == false ) { //if the name is not found
cout << "Not found" <<endl;
Pause();
file << tname << ",0,0\n"; //Add it to the file with 0 wins and losses
}
//Cleanup
file.close();
}
}
I'm curious to know why it doesn't work in the second example as it seems more efficient to open the file only 1 time with the correct flags, do what I need to do and close it.
I have a feeling this might have something to do with the position of the cursor, I have atttempted to use something like file.seekg(0) and file.seekg(0, ios_base::beg) but they don't seem to work as advertised (or I just mis understood the advertisement).
any input would be appreciated.
Edit: The couts were for debugging.
Edit 2: I Suppose I should emphasize the question a little more.
The problem is that the second example does not write to the file where as the first one does. I understand that there might be some concern regarding the !file.eof() condition but in this instance I don't care if it runs an extra time as it wont negatively effect the outcome (additionally, the text file that is being read from has been formatted correctly so that this won't happen).
Edit 3:
I created a very small program that ran:
//Testing bs
fstream file("Test.txt", fstream::in | fstream:: out | fstream::app );
string temp;
//ClearScreen
system(CLEAR_SCREEN);
file << "Line one\n";
getline(file, temp);
file << temp;
file << "Line two\n";
Pause();
return Menu;
Only the first line is written to the file. I'm betting that getline is changing the mode of the stream which is why it is unwritable afterwords.
Final Edit:
after a bunch of research it appears that in the above situation, re-opening the file is the best resolution. Ultimate,y the issue is in the use of getline() vs file.getline(). I'd have to rewrite far too much of the 1000 lines of the program to do it "correctly." Moral of the story? if you are having this issue, spend some time researching the difference between istream::getline and getline(string) and learn to identify when you are going to use which so that you don't get stuck in this situation. Fortunately, it's not imperative I fix it now, but it might be for others in the future.
I can't give you a definite answer, but I can give you a pretty good idea, based on inferences.
You are using fstream (file stream), instances of which are used for dealing with files. If you take a look at the documentation for fstream.open (link), notice that the second parameter is set up such that, by default, it will be either inputting or outputting to a file. Notice that the default is one or the other. This means that you can't assume, when you open the file, that the file exists. More importantly, since you might be inputting from the file, from the perspective of fstream, it shouldn't be assumed that if the file doesn't exist, it should be created.
Another way to think of it: I will assume that you are familiar with ifstream (input file stream) and ofstream (output file stream), which are generally introduced earlier in C++ tutorials/guides than fstream. If you take a look at the documentation for ifstream (link) and for ofstream (link), you'll notice that both of them derive from fstream. Now remember that when you call ifstream.open, if the file doesn't exist, it isn't created - rather, the failbit is set. Contrastingly, when you call ofstream.open, if the file doesn't exist, it is created.
Now, since ifstream and ofstream both derive from fstream, we have two possibilities:
ofstream.open derives directly from fstream.open (ie it has no extended functionality), and we can reasonably expect fstream.open to create file, given that it doesn't exist at first
ifstream.open derives directly from fstream.open, and we can reasonably expect fstream.open not to create a file, given that it doesn't exist at first
It should go without saying that both of these cannot be true; ofstream.open and ifstream.open cannot both derive from the same thing and yet differ in what they do; fstream.open cannot both do and not do something.
If you think about it, the second option is more likely, and here is why: If ofstream.open doesn't directly derive from fstream.open, all it has to do is add an extra step, in which it creates the file if it doesn't exist, and resets the failbit. All of the preceding behavior can be achieved by calling the open function of the parent class. On the other hand, if ifstream.open doesn't directly derive from fstream.open (implying that fstream.open creates the file, given that it doesn't exist at first), ifstream.open must be a complete re-implementation; otherwise there would be no way to skip the step in which the non-existent file is created.
Since it would be less efficient to have a function which re-implements so much than having a different function which simply adds something on, it's more likely that fstream.open doesn't create/open a file if it doesn't already exist.
I realize that this might not be a definitive solution to your problem, but I think this should explain why the second block of code you posted wouldn't (and shouldn't) work. When I look at your first code block (which you said works) I'm not entirely sure what about it makes it work, but I would guess it has something to do with your addition of | fstream::append to the open mode parameter of fstream.open.
I hope this helped.
I want to dynamically read a file for the appended content. The file in written by another thread. I'm using ubuntu, and had a look at inotify, but wanted to try and implement a simple way for this since I only need to read the appended content. What I tried is as follows:
ifstream logFile("path_to_file", ifstream::in);
if(logFile.fail()) {
cout << "file not found" << endl;
exit(0);
}
while (true) {
string line;
getline(logFile, line);
if( logFile.eof() ) {
//wait for 2 seconds
logFile.clear();
}
if(!line.empty())
cout << line << endl;
However, when the EOF is encountered, the flag doesn't get reset when there is more content appended at the end and even if I call clear() to clear the error condition. What can be the issue in this approach? Do I need to open the file in a shared mode?
Thanks.