Does opening an fstream in fstream::out mode erase its current content ? - c++

As the title says , does opening an fstream in fstream::out mode erase its current content ?
If no , what is the the best way to erase a .txt file using the fstream library .
And what is the equivalent of EOF in the C++ fstream library ?

When a std::basic_filebuf opens a file it acts as though it calls the relative C functions (whether it actually does so or not is up to the implementation).
The table in [filebuf.members] outlines what happens when certain flags are passed, if you only pass std::ios_base::out then it acts as though the file were opened with the stdio string "w", which will erase your file if it already exists.
The default for fstream if no flags are passed is to call basic_filebuf::open with std::ios_base::in | std::ios_base::out, which acts as though "r+" were used, which in turn positions the file position at the start of the file, but leaves the contents intact if it already exists.
For reference:

Related

Default mode of fstream

I was looking at the SO post C++ file stream open modes ambiguity. I wanted to know the default file opening mode of fstream. One of the answer says,
What the above implies is that the following code opens the file with
exactly the same open flags fstream f("a.txt", ios_base::in |
ios_base::out); ifstream g("a.txt", ios_base::out); ofstream
h("a.txt", ios_base::in);
So if I understand correctly, in case I create object of fstream, I should be able to either read or write.
But below code does not write any data to file
fstream testFile1;
testFile1.open("text1.txt");
testFile1<<"Writing data to file";
testFile1.close();
However adding mode as given below creates text file with data "Writing data to file"
testFile1.open("text1.txt", ios::out);
So whether the default mode is implementation defined? I am using TDM-GCC-64 toolchain.
The default mode for std::fstreams is std::ios::in|std::ios::out. (Source)
The reason your code doesn't print anything to test1.txt is that the std::ios::in|std::ios::out mode does not create the file if it does not already exist (Source: table on this page).
You can use the std::ios::in|std::ios::app mode, which will start reading from the start, will start writing from the end, and will create the file if it does not exist. Note that using app mode, the file will seek to the end before each write (Source).
The default mode of ifstream is in. The default mode of ofstream is out. That's why they're named that way. fstream has no default mode.
Your example only shows the two defaults, and it shows that by omission of explicit arguments. That fstream f("a.txt", ios_base::in | ios_base::out) uses two explicit arguments is precisely because there is no default mode.

C++ ofstream equivalent to Win32 CreateFile with CREATE_NEW

In an application I want to be sure that I am writing a brand new (binary) file. In Win32 programming I know I can do this with CreateFile using CREATE_NEW, but I can't work out a pure C++ standard way.
Creates a new file, only if it does not already exist.
If the specified file exists, the function fails and the last-error code is set to ERROR_FILE_EXISTS (80).
If the specified file does not exist and is a valid path to a writable location, a new file is created.
I tried using std::ios::out | std::ios::binary | std::ios::ate then seeing if tellp gave me the start of the file or not, but apart from the obvious case that this would still overwrite an empty file, it also seems to truncate a non-empty file anyway as if I used std::ios::trunc...
This was on VS2013, although I assume this is not a compiler/library bug.
The C++ standard doesn't have an API guaranteeing a new file. When opening an existing file in write-only mode without specifying std::ios_base::app it is truncated (independent on whether std::ios_base::trunc is used). I don't know about Windows but on POSIX this would retain the original inode and processes already having opened the file can still access it.
If it is sufficient to get an open and empty file rather than a new one, omiting std::ios_base::in and std::ios_base::app should do the trick (note that opening an std::fstream or an std::ifstream implicitly adds std::ios_base::in).

File handling C++ , opening in ios::app mode, file getting wiped

I am making a programme in turbo C++ which requires input and output to a file as well as retrieving the file data for later use.
fstream file("playlist.txt",ios::in|ios::app);
this is what I use but everytime i close the programme and run it again, all the previous contents get wiped. I thought ios::app "Sets the stream's position indicator to the end of the stream before each output operation".
I tried ios::nocreate also, but to no effect.
You should have fstream::out too:
fstream file("playlist.txt", fstream::in | fstream::out);
Then you can move file pointer to end of file. in and app can't be used together: you need to open for R/W because app implies you won't read.

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).

Replacing data in binary file with fstream and seekp

I'm writing a method to replace a specified string from a binary file and it writes NULLs before the position I set with seekp, then writes the string and closes the stream. I only want to replace some bytes in the file. Before this piece of code I tried out with ofstream with ios::binary and ios::out flags. What's wrong to destroy all data in the file?
Before this piece of code, I open the file with an instance of ifstream to read the same position verifyng the first byte in the string. I only comment this for information.
Thank you all!
The code:
fstream ofs();
ofs.open(nomArchBin,ios::in | ios::out | ios::binary);
if (!ofs.good()) {
cout << "...";
return;
}
ofs.seekp(despEnArchivo,ios::beg);
char* registroChar = registroACadena(reg);
ofs.write(registroChar,cabecera.tamanioReg);
I know this sounds silly, but the only way to open a file for writing
and not to truncate it is to open it for reading as well: if you're
really doing ios::in | ios::out | ios::binary, it should work. (But
since you obviously reentered the code, and didn't copy/paste it, I'm
not sure if this is really what you did.)
Other points you have to pay attention to when trying to seek:
The file must be open in binary mode, and imbued with the "C"
locale. (IMHO, a file opened in binary mode should ignore the locale,
but this isn't what the standard says.)
Both `seekg` and `seekp` have the same effect; using either changes the
position of the other.
The only function which allows seeking to an arbitrary location is
the two argument seek; the one argument form can only be used to seek to
a position previously obtained by a tell.