c++ write to a file, but file is empty - c++

I have this code for turning decimal into binary and write it to a file:
#include <iostream>
#include <fstream>
using namespace std;
int d,num,s,r,k,sum=0;;
void main()
{
ofstream myfile;
myfile.open("binary.txt",ios::in);
cin >> d;
while(d>0)
{
r=d%2;
sum=sum + (k*r);
d=d/2;
k=k*10;
myfile << sum;
}
cout << "Encryption Succesfull"<<endl;
myfile.close();
}
The program runs successfully, but the file is empty.
The file name is right, no syntax errors, etc.
What to do?

You use the wrong flags for opening the file:
myfile.open("binary.txt",ios::in);
It should be
myfile.open("binary.txt",ios::out | ios::binary);

myfile.open("binary.txt",ios::in);
opens the file for reading. If you want to output something, use ios::out or leave the param empty (since the default value is ios_base::out anyhow):
myFile.open("binary.txt");
I've found this line on cplusplus.com, but it doesn't seem to be true (tested on devC++ 4.9.9.2, uses some MinGW version):
out is always set for ofstream objects (even if explicitly not set in argument mode).
Removing the second parameter or changing it to ios::out does fix the problem.

Related

Why does ofstream work here, but not fstream?

I am trying to understand a difference between std::ofstream and std::fstream. I have this code:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main () {
string line;
//create an output stream to write to the file
//append the new lines to the end of the file
ofstream myfileI ("input.txt", ios::app);
if (myfileI.is_open())
{
myfileI << "\nI am adding a line.\n";
cout << myfileI.fail() << "\n";
myfileI << "I am adding another line.\n";
cout << myfileI.fail() << "\n";
myfileI.close();
}
else cout << "Unable to open file for writing";
The fail bits return 0, so it is writing.
But the fail bits return 1 when I use the exact same code but instead use fstream instead of ofstream.
input.txt is just this:
Read and write to this file.
What am I doing here?
This is not a good example of a file
I see no practical difference between the two cases you describe.
The ONLY technical difference is that ofstream always has the ios::out flag enabled, which will be added to any flags you specify. Whereas fstream has the ios::in and ios::out flags enabled by default, but will be overriden by any flags you specify.
So, in the ofstream case you are opening the file in ios::out | ios::app mode, whereas in the fstream case you are opening the file in just ios::app mode.
But, both streams delegate to std::filebuf, and according to this reference for std::filebuf::open(), both out|app and app modes act the exact same way - as if fopen(filename, "a") were used, thus they will both "Append to file" if the file exists, and "Create new" if the file does not exist.

How to append to a file in C++?

I want to print some data to a file with a few separate calls. I noticed that the default behaviour for a write overwrites the previously written data.
#include <iostream>
#include <fstream>
using namespace std;
void hehehaha (){
ofstream myfile;
myfile.open ("example.txt");
myfile << "Writing this to a file.\n";
myfile.close();
}
int main () {
for(int i=0; i <3 ; i++){
hehehaha();}
return 0;
}
this code writes only one line Writing this to a file. but what I want is the following:
Writing this to a file.
Writing this to a file.
Writing this to a file.
Open the file in app mode instead myfile.open("example.txt", std::ios_base::app);
The default open mode for ofstream is plain out, which recreates the file from scratch (if the file exists, its contents is truncated).
To append to a file you need to use the app mode, or add the flag ate.
The table in this open reference is quite helpful to understand the open-modes and what they do.

Write to the middle of an existing binary file c++

I'm trying to open a binary file for writing without erasing the content. But I do not want to write to eof. I want to write to a specific position in file.
Here is a litte example:
ofstream out("test.txt", ios::binary | ios::app);
for(int i = 0; i < 100; i++)
out.put('_');
out.write("Hallo", 5);
out.close();
ofstream out2("test.txt", ios::binary | ios::app);
out2.seekp(10);
out2.write("Welt", 4);
out2.close();
If using app, seek doesn't work. If not using app opening file erases data. Does anybody know an answer?
try the second overload of seekp, which allows you to provide an offset and a direction, this could be begining of file in your case (i.e. ios_base::beg). This of course assumes you know what you are doing and all you want to do is overwrite an existing number of characters.
EDIT: here is fully working example:
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
{
ofstream out("test.txt", ios::binary);
for(int i = 0; i < 100; i++)
out.put('_');
out.write("Hallo", 5);
}
{
fstream out2("test.txt", ios::binary | ios::out | ios::in);
out2.seekp(10, ios::beg);
out2.write("Welt", 4);
}
}
When opening with ios::app, it is as if you open a new file that just happened to be attached to an existing file: you can not access the existing file. I'm not sure, because I would do as in Kerrek's answer, but if you really want to try, you probably have to open with "ios::in | ios::out", similar to fopen("test.txt", "rw").
Or as crashmstr points out: ios::out might be enough.
You cannot magically extend the file from the middle. Perhaps easiest to write to a new file: First copy the initial segment, then write your new data, then copy the remaining segment. When all is done, you can overwrite the original file.
According to the specification of fstream here
fstream::open
the ios::app "Sets the stream's position indicator to the end of the stream before EACH output operation." So ios::app doesn't work for replacing, seeks of any sort fail, at least for me.
Just using ios::out does wipe out the file contents preserving only the size, basically turning the file into trash.
ios::in|ios::out turned out as the only working thing for me.
Working Code: This code searches for a string (OLD-STRING) in cout.exe and replaces with a new string (NEW-STRING).
`#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main(int argc, char *argv[])
{
fstream ifs;
ifs.open ("C:\\Users\\user\\Desktop\\cout.exe", fstream::binary | fstream::in | fstream::out);
std::string str((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());
size_t pos = str.find("OLD-STRING");
if (pos != string::npos)
{
cout << "string found at position: " << int(pos) << endl;
ifs.seekp(pos);
ifs.write("NEW-STRING", 10);
}
else
{
cout << "could not find string" << endl;
}
if (ifs.is_open())
ifs.close();
return 0;
}`

Why can't I read and append with std::fstream on Mac OS X?

Consider the following C++ program, which takes a file and prints each line. It's a slice of a larger program where I later append to the file, based on what I see.
#include <fstream>
using std::fstream;
#include <iostream>
#include <string>
using std::string;
int main()
{
fstream file("file.txt", fstream::in | fstream::out | fstream::app);
string line;
while (std::getline(file, line))
std::cerr << line << std::endl;
return 0;
}
Now apply this version of file.txt (One word on the first line, followed by a newline):
Rain
On my machine (Snow Leopard), this prints out nothing. On closer inspection, the first call to getline fails. Strangely, it also fails if I add a second line: still nothing is printed!
Can anyone solve this mystery?
When you say:
fstream file("file.txt", fstream::in | fstream::out | fstream::app);
you open the file in append mode - i.e. at the end. Just open it in read mode:
fstream file("file.txt", fstream::in );
or use an ifstream:
ifstream file("file.txt" );
And of course as Earwicker suggests, you should always test that the open succeeded.
If you are determined to open in append mode, you can move the read pointer explicitly:
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
int main() {
fstream file( "afile.txt", ios::in | ios::out | ios::app );
if ( ! file.is_open() ) {
cerr << "open failed" << endl;
return 1;
}
else {
file.seekg( 0, ios::beg ); // move read pointer
string line;
while( getline( file, line ) ) {
cout << line << endl;
}
}
}
Edit: It seems that the combination of flags used in the opening of the file leads to implementation specific behaviour. The above code works with g++ on Windows, but not with g++ on Linux.
You should check if the file has actually been opened:
if (!file)
std::cerr << "Oh dear" << std::endl;
Update: in fact the file likely has been opened, but is in append mode - see Neii's answer.
Update 2: okay, wrong again. In Leopard's g++ at least, the file will not be opened because the app flag is incompatible with the in flag. So the above check will print Oh dear.
In MSVC++, it goes ahead and opens the file, apparently with the read position at the start, which explains why other people saw it work and I apologise for doubting their veracity!

ifstream::open not working in Visual Studio debug mode

I've been all over the ifstream questions here on SO and I'm still having trouble reading a simple text file. I'm working with Visual Studio 2008.
Here's my code:
// CPPFileIO.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <fstream>
#include <conio.h>
#include <iostream>
#include <string>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
ifstream infile;
infile.open("input.txt", ifstream::in);
if (infile.is_open())
{
while (infile.good())
cout << (char) infile.get();
}
else
{
cout << "Unable to open file.";
}
infile.close();
_getch();
return 0;
}
I have confirmed that the input.txt file is in the correct "working directory" by checking the value of argv[0]. The Open method just won't work.
I'm also having trouble debugging- should I not be able to set a watch on infile.good() or infile.is_open()? I keep getting
Error: member function not present.
EDIT: Updated code listing with full code from .CPP file.
UPDATE: The file was NOT in the Current Working Directory. This is the directory where the project file is located. Moved it there and it works when debugging in VS.NET.
Try using the bitwise OR operator when specifying the open mode.
infile.open ("input.txt", ios::ate | ios::in);
The openmode parameter is a bitmask. ios::ate is used to open the file for appending, and ios::in is used to open the file for reading input.
If you just want to read the file, you can probably just use:
infile.open ("input.txt", ios::in);
The default open mode for an ifstream is ios::in, so you can get rid of that altogether now. The following code is working for me using g++.
#include <iostream>
#include <fstream>
#include <cstdio>
using namespace std;
int main(int argc, char** argv) {
ifstream infile;
infile.open ("input.txt");
if (infile)
{
while (infile.good())
cout << (char) infile.get();
}
else
{
cout << "Unable to open file.";
}
infile.close();
getchar();
return 0;
}
Sometimes Visual Studio puts your exe file away from your source code. By default VS may only look for the file starting from your exe file. This process is a simple step for getting the input txt file from the same directory as your source code. Should you not want to fix your IDE setup.
using namespace std;
ifstream infile;
string path = __FILE__; //gets source code path, include file name
path = path.substr(0,1+path.find_last_of('\\')); //removes file name
path+= "input.txt"; //adds input file to path
infile.open(path);
Hopefully this helps other people for a quick solution. It took me a while to find this setup myself.
I've found two problems in your code:
a) syntax error in "ios::ate || ios::in" => should be "ios::ate | ios::in"
b) "ios::ate" sets the cursor to the end of file - so you get nothing when you start reading
So just remove "ios::ate" and you are fine :)
ciao,
Chris
infile.open ("input.txt", ios::ate || ios::in);
|| is the logical or operator, not the bitwise operator (as Bill The Lizzard said).
so i guess you are doing the equivalent to:
infile.open ("input.txt", true);
(assuming neither ios::ate or ios::in are 0)
Try using:
ifstream fStm("input.txt", ios::ate | ios::in);
I'm also having trouble debugging- should I not be able to set a watch on "infile.good()" or "infile.is_open()"? I keep getting "Error: member function not present."
and the proper includes:
#include <fstream>
etc.
If you use the default Vs code setup, place the text file that you want to read from in the same folder as your executable, I know it is not pretty but yeah it works