Writing/reading in to binary/text files - c++

wFile.open(fileName, ios::out | ios::trunc);
if (!(wFile.is_open()))
{
cout << "Error in opening the file" << endl;
return false;
}
else
{
for (unsigned int i = 0; i < Widgets.size(); i++)
{
Widgets.at(i)->copyToBinary(fileName);
}
wFile.close();
return true;
}
I'm trying to copy different objects types from a vector. My problem is that when this code runs for the copy, it only copies the last object. It seems like the code just overrides the existing text.
Also, I have this code in each class (this is the copyToBinary function):
ofstream file(fName);
file << *this;
file << endl;
What am I missing here?

Problem:
You pass the finename to copyToBinary(), reopening a stream and overwriting it.
Solution:
Pass the wFile stream as reference and write to it without reopening each time
void copyToBinary(ostream& file) {
file << *this;
file << endl;
}

You should not reopen the file in copyToBinary. Pass wFile as argument not filename :
...copyToBinary(ostream &file) {
file << *this;
file << endl;
}
and call ...copyToBinary(wFile).

First, when you are opening the file
wFile.open(fileName, ios::out | ios::trunc);
Everytime it is called the existing content get lost as you are using trunc mode. It will be better if you use ios::app mode. So that whenever the above code runs, it opens the file in append mode.
Second, You are passing the filename in the copyToBinary function. And By using the default constructor
ofstream file(fName);
your file is getting opened everytime in default ios::out mode but not in ios::app mode. It will be better either you pass the refernece of opened file or open the file in function as append mode.

Related

How to save and also read c++ fstream file without closing it

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.

std::ofstream appending files

So I want to input something in a file but it doesn't seem to work. My code is this:
ofstream f("reservedTables.DAT");
cin >> table;
f.open("reservedTables.DAT", ios::out | ios::app);
f << table;
f.close();
What am I doing wrong? I write the number for the variable table but it doesn't appear in the file that I put it in
Quick walk through:
ofstream f("reservedTables.DAT");
Allocates stream and opens the file.
cin >> table;
Reads in input from user.
f.open("reservedTables.DAT", ios::out | ios::app);
Attempts to re-open the file. Will fail.
f << table;
Stream is in failed state after failed open and cannot be written.
f.close();
closes file.
Solution
Only open the file once and check for errors.
ofstream f("reservedTables.DAT", ios::app); // no need for ios::out.
// Implied by o in ofstream
cin >> table;
if (f.is_open()) // make sure file opened before writing
{
if (!f << table) // make sure file wrote
{
std::cerr << "Oh snap. Failed write".
}
f.close(); // may not be needed. f will automatically close when it
// goes out of scope
}
else
{
std::cerr << "Oh snap. Failed open".
}
That's because you are opening the file twice.
If you call open, you are actually calling rdbuf()->open(filename, mode | ios_base::out). Note that (ref):
If the associated file was already open, returns a null pointer right away.
Because a null pointer has been returned, it is assigned to the internal file buffer, and no file is opened anymore. This means that any attempts to write to it fail.
The constructor already opens the file if you specify a filename, so you don't need to call open:
std::ofstream f("reservedTables.DAT");
std::cin >> table;
f << table;
f.close();

Writing file doesn't work properly

I'm trying to save some of my input to a file, but it doesn't seem to work. I don't know if its the file extension or whatever, but I've tried to modify it for an hour now, however it doesn't pop-up some file in my folder.
This is how my code works (not posting everything, would be too long)
This is my function:
void mobiltelefon::savePhoneOnFile() const
{
ofstream out;
out.open("C:\\temp\\phones.txt", ios::in);
out << this->numberofphones << endl;
for (int i = 0; i < this->numberofphones; i++) {
out << this->phones[i]->getPhonename() << endl;
out << this->phones[i]->getPrice() << endl;
}
out.close();
}
This is how I call it in main:
case 7:
cout << "Save the phones on file" << endl;
fb.savePhoneOnFile();
break;
I can't see my mistake. Why doesn't the file show up a file in my folder when I try to save it?
If you are trying to open the file for writing, you should be using ios::out as the second argument
ofstream out("C:\\temp\\phones.txt", ios::out);
The various open modes are
app seek to the end of stream before each write
binary open in binary mode
in open for reading
out open for writing
trunc discard the contents of the stream when opening
ate seek to the end of stream immediately after open
Here:
ofstream out;
out.open("C:\\temp\\phones.txt", ios::in);
You don't want to have the std::ios::in flag. Why would you? You're writing to a file, not reading from it.
Explained: std::ofstream bitwise-ORs the flag argument with std::ios_base::out in its constructor and passes it to std::basic_filebuf::open. Look up out | in in that link and you have the answer. The file would need to exist to be open properly. It won't be created.
Just leave out that parameter completely and it will be defaulted to std::ios_base::out (that's what you should have had):
out.open("C:\\temp\\phones.txt");
You might as well do it at once at construction:
std::ofstream out("C:\\temp\\phones.txt");

ofstream, when will it fail instead of creating a new file?

i just started reading on how to open and edit files.
when working with ifstream, if the file doesnt exist, it wont be created.
in reference to the code below, when would the condition (!outfile) be false, as if the file doesn't exists it will simply be created by the constructor, hence always making the condition false.
int main()
{
ofstream outfile ("test1.txt");
if (!outfile)
{
cout << "cannot create file test1.txt" << endl;
return 1;
}
outfile << 10 << " " << 345.12 << endl;
outfile << "This is a short text file";
outfile.close();
system("PAUSE");
return 0;
}
One way opening an ofstream could fail is if the file in the given path exists, but you do not have the permission to write to it. Alternatively, if the file does not exist but you do not have permission to create a file in the given path, opening the ofstream should also fail.
Another failing situation could be if the files does not exist, and the underlying device does not have sufficient free space/inodes to create one.

Writing to file results in empty file

I wrote a small program that opens a file, builds a vector from every line in the file and then have the user able to add/remove from the file. The program first removes from the vector, then rebuilds the file based on the vector. Here's the code that rebuilds the file (fileName is a member variable with the full name of the text file, ex. "test.txt":
bool rebuildFile() {
if (remove(fileName.c_str()) == 0) { // remove the old file
ofstream newFile(fileName); // create new file with same name
newFile.open(fileName, ios::app); // open to append to end of file
if (newFile.is_open()) {
newFile << fileHeader << endl; // add the first header line
for (int i = 0; i < myVector.size(); i++) { // loop through vector, adding strings to file
newFile << myVector[i] << endl; // I used "\n" instead of endl, but both give same results
}
newFile.close();
return true; // success
}
}
return false; // failure
}
After this function exits, the file is completely empty. So it clearly creates a new file, but then the writing part is an issue, and I can't figure out why. I read other posts where some had issues where they had the file open in Notepad/Notepad++, but I've always made sure to close that specific file before running the program. I'm not sure if the ios::app flag is causing an issue with the loop, but the documentation seems clear that it just points to the end of the file every time you output to it, so I don't think the issue is there. Any thoughts?
EDIT:
Apparently you can't append to an empty file... This new code works, but I'm not sure if there's a "cleaner" way to add to a file in two different ways without opening and closing it twice using different flags.
new code:
bool rebuildFile() {
if (remove(fileName.c_str()) == 0) {
std::ofstream newFile(fileName);
newFile.open(fileName);
if (newFile.is_open()) {
newFile << fileHeader << endl;
newFile.close();
}
newFile.open(fileName, std::ofstream::out | std::ofstream::app);
if (newFile.is_open()) {
for (int i = 0; i < myVector.size(); i++) {
newFile << myVector[i] << endl;
}
newFile.close();
return true;
}
}
return false;
}
Trying to call open on an already open file stream puts the stream in a failed state.
Just change
ofstream newFile(fileName); // create new file with same name
newFile.open(fileName, ios::app);
to
ofstream newFile(fileName, ios::app);
[ofstream.members]
void open(const char* s, ios_base::openmode mode = ios_base::out);
Effects: Calls rdbuf()->open(s, mode | ios_base::out). If that
function does not return a null pointer calls clear(), otherwise calls
setstate(failbit) (which may throw ios_base::failure (27.5.5.4)).
[filebuf.members]
basic_filebuf<charT,traits>* open(const char* s, ios_base::openmode mode);
Effects: If is_open() != false, returns a null pointer. [...]
bool is_open() const;
Returns: true if a previous call to open succeeded (returned a
non-null value) and there has been no intervening call to close.
ofstream newFile(fileName);
doesn't just create the file, it opens it too. And that means you can't open it again.
I don't see a reason to remove the file, re-create it - truncating if it exists - and open it, write a little, close the file, open it again but for appending, and then write to it some more.
Plus, if you run out of luck, there's an opportunity for a different process to modify (or delete) the file between the first close and the second open, which is in general not a good thing.
This snippet should work:
bool rebuildFile()
{
std::ofstream newFile(fileName);
if (newFile)
{
newFile << fileHeader << endl;
for (int i = 0; i < myVector.size(); i++) {
newFile << myVector[i] << endl;
}
}
return newFile;
}
(Files are closed automatically, if needed, by ofstream's destructor.)