Read/write file only if it exists using fstream - c++

I'm handling a file using fstream, and I need to read and write to it. However, even using std::ios:in, the file continues to be created if it does not exist:
std::fstream file("myfile.txt", std::ios::in | std::ios::out | std::ios::app);
Any thoughts?
Thanks in advance!

Read documentation carefully:
std::basic_filebuf<CharT,Traits>::open - cppreference.com
The file is opened as if by calling std::fopen with the second argument (mode) determined as follows:
mode
openmode & ~ate
Action if file already exists
Action if file does not exist
"r"
in
Read from start
Failure to open
"w"
out, out|trunc
Destroy contents
Create new
"a"
app, out|app
Append to file
Create new
"r+"
out|in
Read from start
Error
"w+"
out|in|trunc
Destroy contents
Create new
"a+"
out|in|app, in|app
Write to end
Create new
"rb"
binary|in
Read from start
Failure to open
"wb"
binary|out, binary|out|trunc
Destroy contents
Create new
"ab"
binary|app, binary|out|app
Write to end
Create new
"r+b"
binary|out|in
Read from start
Error
"w+b"
binary|out|in|trunc
Destroy contents
Create new
"a+b"
binary|out|in|app, binary|in|app
Write to end
Create new
This should explain everything.
Just drop app flag and you done.
https://wandbox.org/permlink/p4vLC8ane9Ndh1gN

There are different approaches, you can do it the old way
std::fstream file("myfile.txt", std::ios::in | std::ios::out); // edited after comment
if (!file)
{
// Can't open file for some reason
}
Or you can use standard library std::filesystem::exists introduced in C++17. Read more about it.
if (std::filesystem::exists("myfile.txt")) { // Exists }
Remember that file can exist but you can fail to interact with it (read/write from/to it).
If needed:
g++ -std=c++17 yourFile.cpp -o output_executable_name

Related

What happens when ios::in mode is specified with an output file stream?

What is the purpose of ios::in and ios::out modes while creating file streams in c++? I have created an output file stream as
ofstream myout("file.txt",ios::in); This is an output file stream but ios::in mode is specified. What is the effect of ios::in mode in output stream and similarly ios::out mode in input file stream?
I have looked here, but couldn't understand.
Per std::basic_filebuf<CharT,Traits>::open(), which better explains what the various flag combinations actually do:
The file is opened as if by calling std::fopen with the second argument (mode) determined as follows:
mode
openmode & ~ate
Action if file already exists
Action if file does not exist
"r"
in
Read from start
Failure to open
"w"
out, out|trunc
Destroy contents
Create new
"a"
app, out|app
Append to file
Create new
"r+"
out|in
Read from start
Error
"w+"
out|in|trunc
Destroy contents
Create new
"a+"
out|in|app, in|app
Write to end
Create new
"rb"
binary|in
Read from start
Failure to open
"wb"
binary|out, binary|out|trunc
Destroy contents
Create new
"ab"
binary|app, binary|out|app
Write to end
Create new
"r+b"
binary|out|in
Read from start
Error
"w+b"
binary|out|in|trunc
Destroy contents
Create new
"a+b"
binary|out|in|app, binary|in|app
Write to end
Create new
If openmode is not one of the modes listed, the open() fails.
If the open operation succeeds and openmode & std::ios_base::ate != 0 (the ate bit is set), repositions the file position to the end of file, as if by calling std::fseek(file, 0, SEEK_END), where file is the pointer returned by calling fopen. If the repositioning fails, calls close() and returns a null pointer to indicate failure.
If the associated file was already open, returns a null pointer right away.

File cleared out after reopening it with std::fstream

I want to open a file for reading, close it, and then open it again for writing using the same std::fstream. But when I reopen the file with writing permissions all the data inside is being cleared and it becomes 0 bytes long.
Here's my code:
char* data = new char[5];
std::fstream fs("myFile", std::ios::binary | std::ios::in);//opening with read
fs.read(data, 5);
fs.clear();
fs.close();
//Do some stuff
fs.open("myFile", std::ios::binary | std::ios::out);//opening with write
//The file is already empty at this point
When opening a file with the default write flag, i.e., std::ios::out with the <iostream> facility or "w" with the <cstdio> functions, there is a combination of POSIX flags happening behind your back - a truncate flag is added. This means that upon opening in write mode, the file content is discarded. To circumvent this, open the file the second time with
fs.open("myFile", std::ios::binary | std::ios::app);
The append mode moves the file cursor to the end of the file at each write operation and is not combined with the truncate flag, see here. Note that when you want to write to arbitrary positions in the existing file, you need to open it with
fs.open("myFile", std::ios::binary | std::ios::in | std::ios::out);
which does not truncate its content and allows for cursor positioning with the seek* functions.

ifstream not creating and opening a file for output

I am developing in C++ using NetBeans 6.9 on Ubuntu 11.04. I have declared the input and output file name strings and file streams thus
ifstream fpInputFile, fpOutputFile;
string inputFileName="", outputFileName="";
The input file name is assigned the name of an existing file as an input argument to the application. The output file name is given the same as the input name except that "_output" is inserted before the final period. So the output is written to the same directory as the input is located. Also I start netbeans with
su netbeans
so the IDE has root privileges to the directory. I try to open the files, and check whether they are opened thus.
fpInputFile.open(inputFileName.c_str(), ifstream::in);
fpOutputFile.open(outputFileName.c_str(), ifstream::out);
if (!(fpInputFile.is_open())) throw ERROR_OPENING_FILE;
if (!(fpOutputFile.is_open())) throw ERROR_OPENING_FILE;
The input file opens successfully but the output file does not.
Any help in determining why the output file is not opening for writing would be most appreciated.
Declare the output file as an ofstream rather than a ifstream.
You could also use a fstream for both input and output files.
The obvious problem is that you probably meant to open the file using a std::ofstream rather than an std::ifstream. This helps with actually writing to the stream although there are ways to write to an std::ifstream as long as it is opened for reading. For example, you could use the std::streambuf interface directly or use the std::streambuf to construct and std::ostream.
The more interesting question is: why isn't the file opened for writing when std::ios_base::in | std::ios_base::out is used for the open mode? std::ifstream automatically adds std::ios_base::in. It turns out, that the mode std::ios_base::in | std::ios_base::out doesn't create a file but it would successfully open an existing file. If you really want use an std::ifstream to open a file for output which potentially doesn't exist you would need to use either std::ios_base::out | std::ios_base::trunc or std::ios_base::out | std::ios_base::app:
the former would force the file to be created or truncated if it exists
the latter would force writes to append to the file in all cases
My personal guess is, however, that you are best off just using std::ofstream or, if you want to open the file for both reading and writing std::fstream (which, however, would also need to have std::ios_base::trunc or std::ios_base::app added to create a file if none exists).

How to edit (read and then write) a file with c++ filestreaming?

For example, if I need to add a sentence to the end of a file. I have to first open the file (e.g. "a.txt"), by
ofstream outfile.open("a.txt");
But whenever I do this, I will overwrite the existing "a.txt" in the same directory. Is it possible to edit the file like first read and then write?
Thank you very much.
You want to open the file in 'append' mode. Passing ios::app to the open method causes the file to be opened in append mode.
f.open("file.txt", ios::app);
See http://www.cplusplus.com/reference/iostream/ios_base/openmode/ for other flags
Try this:
std::ofstream outfile( "a.txt", std::ios_base::app | std::ios_base::ate );
Various references:
http://www.cplusplus.com/reference/iostream/ofstream/ofstream/
http://www.cplusplus.com/reference/iostream/ofstream/open/
http://msdn.microsoft.com/en-us/library/aa277521(v=vs.60).aspx
http://msdn.microsoft.com/en-us/library/aa266859(v=vs.60).aspx

c++ std::fstream behaviour on MacOS

On MacOS with gcc4.2 should the following code create a new file if none exists?
#include <fstream>
void test () {
std::fstream file ("myfile.txt", std::ios::in | std::ios::out);
}
By my logic it should, either open up an existing file for read/writing or create a new empty file for read/writing. But the behaviour I get is that it will not create a new file if 'myfile.txt' does not exist.
How do I get the same behavior as fopen("myfile.txt", "r+"); ?
Furthermore,
#include <fstream>
void test () {
std::ofstream file ("myfile.txt", std::ios::in | std::ios::out);
}
Will always truncate an existing file...
Is this the standard behavior?
First of all, I have no idea why you think that fopen("r+") creates a file if it doesn't exist - according to ISO C & C++, it does not, it just opens an existing file for read/write. If you want to create a file with fopen, you use "w+".
For streams, you just specify trunc:
std::ofstream file ("myfile.txt",
std::ios::in | std::ios::out | std::ios::trunc);
However, both this and fopen("w+") will truncate the file. There's no standard way to open the file without truncating if it exists, but create it if it does not exist in a single call. At best you can try to open, check for failure, and then try to create/truncate; but this may lead to a race condition if file is created by another process after the check but before truncation.
In POSIX, you can use open with O_CREAT and without O_TRUNC.
For the first case, you have specified that you are BOTH reading from and writing to the file. Hence, it will fail, if the file does not already exist. You could try to use two separate streams (one for reading and the other for writing), and construct the output stream, first. As for the second case, you can use "std::ios::app" (open in append mode) to prevent truncation. [Tested with Mac OS X 10.4.11, GCC 4.0.1]