std::ofstream appending files - c++

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();

Related

File stream with repeating input

I'm attempting to create a repeating menu that will allow a user to re-enter a file name if the program is unable to open the file.
Right now it works correctly if I enter the name of an existing file, but if the file doesn't exist it prints the "File not found" then executes the rest of the program. I'm new to file streams and most of the code here was found through references. I'm a bit lost on what exactly is going on and what the best way to handle the situation is. Any guidance would be appreciated.
typedef istream_iterator<char> istream_iterator;
string fileName;
ifstream file;
do {
cout << "Please enter the name of the input file:" << endl;
cin >> fileName;
ifstream file(fileName.c_str());
if (!file) {
cout << "File not found" << endl;
}
} while (!file);
std::copy(istream_iterator(file), istream_iterator(), back_inserter(codeInput));
After constructing the object file will always exist, so your loop condition always fails. Change the condition to whether the file didn't open properly.
do {
...
}
while (!file.is_open())
this code will work.
do {
std::cout << "Please enter the name of the input file:" << std::endl;
std::cin >> fileName;
file = std::ifstream(fileName.c_str());
if (!file) {
std::cout << "File not found" << std::endl;
}
} while (!file);
your error was that you have 2 definition of the file variable.
the variable in while (!file) that is used is the one defined outside the do-while loop, and it is valid state is set to true by default.
In addition to #acraig5075 answer:
Writing a type then a variable name (ifstream file) is to create a new variable. Obviously you know this, but if you use the same name again in, for example, a loop, it makes a new and distinct variable.
ifstream file; // a unique variable
...
do {
...
ifstream file(fileName.c_str()); // another unique variable
...so change the usage inside the loop to:
file.open(fileName.c_str());

What is the difference among ios::app, out, and trunc in c++?

I know that the default file open mode is out. And I think out will overwrite the data in the file, but in the following code, it age data doesn’t overwrite name data.
#include <fstream>
#include <iostream>
using namespace std;
int main () {
char data[100];
// open a file in write mode.
ofstream outfile;
outfile.open("afile.dat");
cout << "Writing to the file" << endl;
cout << "Enter your name: ";
cin.getline(data, 100);
// write inputted data into the file.
outfile << data << endl;
cout << "Enter your age: ";
cin >> data;
cin.ignore();
// again write inputted data into the file.
outfile << data << endl;
// close the opened file.
outfile.close();
// open a file in read mode.
ifstream infile;
infile.open("afile.dat");
cout << "Reading from the file" << endl;
infile >> data;
// write the data at the screen.
cout << data << endl;
// again read the data from the file and display it.
infile >> data;
cout << data << endl;
// close the opened file.
infile.close();
return 0;
Then I’m confused about the three open mode for file – app, out, trunc.
If for name I enter “Zara” and age “9”, the output should be “9ara”. However, it is not. It is “Zara 9”.
ios::out is the default mode for std::ofstream, it means that output operations can be used (i.e. you can write to the file).
ios::app (short for append) means that instead of overwriting the file from the beginning, all output operations are done at the end of the file. This is only meaningful if the file is also open for output.
ios::trunc (short for truncate) means that when the file is opened, the old contents are immediately removed. Again, this is only meaningful if the file is also open for output.
Your code just uses the default ios::out mode. So it starts writing from the beginning of the file, but doesn't remove the old contents. So the new contents will overlay what's already there -- if the file is originally 10 bytes long, and you write 3 bytes, the result will be the 3 bytes you write followed by the remaining 7 bytes of the original contents. More concretely, if the file originally contains:
Firstname Lastname
30
and you write FN LN and then 20 (with newlines after each), the resulting file will look like:
FN LN
20
Lastname
30
because you only overwrite the first 9 bytes of the file (assuming Unix-style newlines).
Once you've opened the file, all outputs to the file are written sequentially after each other, unless you use outfile.seekp() to go to a different location. It doesn't go back to the beginning of the file for each thing you write. seekp() has no effect if the ios::app is used; then every write goes at the end of the file.
Just a little correction to Barmar's answer. I think that the type ofstream implies not only the ios::out, but also the ios::trunc (and I'm not sure, but the ios::out could also imply the ios::trunc).
Here's the concrete example:
ofstream fich;
fich.open("archivo.txt");
for (unsigned i = 0; i < ag.n_pers && !fich.fail(); ++i) {
escribir_persona(fich, ag.pers[i]);
}
if (fich.fail()) {
ok = ERROR;
}
else {
ok = OK;
}
fich.close();
When I call this function, the data of the file is completely overwrited (even if the data to write is less than that which was writen previously), and if the data to write is empty, this just deletes everything in the file.

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");

Writing/reading in to binary/text files

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.

Failbit set when trying to read from file - why?

I'm trying to write a function that automatically formats XML-Strings; but I'm already failing when I try to read text from a file and write it into another one.
When I use my function sortXMLString()
bool FormatXML::sortXMLString()
{
string XMLString;
ifstream fin("input.txt");
fin.open("input.txt", ios::in);
ofstream fout("output.txt");
fout.open("output.txt", ios::out);
if (fin.is_open() && fout.is_open())
{
if (fin.good()) cout << "good" << endl;
if (fin.fail()) cout << "fail" << endl;
if (fin.bad()) cout << "bad" << endl;
while (getline(fin, XMLString))
{
//TODO: Formatting
fout << &XMLString << endl;
}
fin.close();
fout.close();
}
else return false;
return true;
}
I will get the output "fail", but the function never enters the while-loop. The function returns true.
It doesn't matter what I write into my input.txt (a single letter, a single number, multiple lines of text or even nothing), the failbit will always be set before getline can even be reached.
Why is this/ how can I properly read out of my file?
ifstream fin("input.txt"); will open the file with fin as stream object why calling open member function again ? same goes for fout object too.
Calling open on an already open stream fails, meaning the failbit flag is set to true.
Just open once
ifstream fin("input.txt");
ofstream fout("output.txt");