Is ios::in needed for ifstream's opened in binary mode? - c++

What's the difference between these two? Isn't the in flag object thing redundant? Thanks.
std::ifstream file1("one.bin", std::ifstream::in | std::ifstream::binary);
std::ifstream file2("two.bin", std::ifstream::binary);

From the docs on ifstream class constructor:
binary (binary) Consider stream as binary rather than text.
in (input) Allow input operations on the stream.
So when reading from a file, I would use std::ifstream::in flag not because it's required (or not) but because it would be a good programming practice to let a programming interface know what you are going to use it for.
Edit:
The following is taken from http://www.cplusplus.com/doc/tutorial/files/, about open() member function though (but the constructors in the code in the question probably call open() copying the mode flags without modification).
class: default mode parameter
ofstream: ios::out
ifstream: ios::in
fstream: ios::in | ios::out
For ifstream and ofstream classes, ios::in and ios::out are
automatically and respectively assumed, even if a mode that does not
include them is passed as second argument to the open() member
function.
Nevertheless, many examples over the Web use ifstream::in when showing a construction of an ifstream object. Could really be some kind of a superstition practice, instead of a programming one.

binary, in this case, only refers to the method of reading or writing. In regular mode on windows, '\n' is translated to '\r''\n'. This can affect both reading and writing, so binary mode turns this off. out|binary makes just as much sense as in|binary

I can't find authoritative documentation online.
Edit I can't even find a proper reference in my copy the Josuttis Book, 8th printing. It should have been in section 13.9 pp. 627-631
Empirical evidence suggests it is redundant IFF none of std::ios::in or std::ios:out are passed:
#include <fstream>
#include <iostream>
int main(int argc, char** args)
{
std::ifstream ifs(args[0], std::ios::binary);
std::cout << ifs.rdbuf() << std::flush;
return 0;
}
Succeeds:
test | md5sum
md5sum test
show the same hash sum.
// ...
std::ifstream ifs(args[0], std::ios::out | std::ios::binary);
will fail (zero bytes output)
test | wc -c # shows 0

From cplusplus.com reference page, there is no difference.
in is always set for ifstream objects (even if explicitly not set in argument mode).
It's the same for ofstream. Therefore, you don't need to set std::ios::in for ifstream or std::ios::out for ofstream, even if you have set std::ios::binary which omits the in/out mode.

Related

Why can an `ifstream` be opened both for reading and writing?

I've seen an interesting piece of code today:
ifstream fil;
fil.open( "ini.txt", std::ios::in | std::ios::out );
I was just about to rant about its brokenness, but to my astonishement I saw that cppreference.com apparently thinks this is correct:
http://en.cppreference.com/w/cpp/io/basic_ifstream/open
mode - specifies stream open mode. It is bitmask type, the following constants are defined:
in: open for reading
out: open for writing
How can an ifstream, which, as far as I understand is an INPUT file stream, be opened both for reading and writing?
Shouldn't it necessarily be fstream instead of ifstream?
std::ifstream is like a handle over a std::basic_filebuf. You can even access that buffer from the handle with a call to std::basic_ifstream::rdbuf.
You can steal that buffer from the handle, and assign it to another (I won't go into how it's done). And here's the interesting thing. You can move that very buffer from an ifstream to an ofstream. And that requires being able to open the buffer for writing. As such, the very same reference page you linked says this:
Effectively calls rdbuf()->open(filename, mode | ios_base::in)
This is a convenience function to avoid manipulating the buffer itself later.
you need to use fstream:
fstream file("input.txt", ios::in | ios::out | ios::app);
int data;
file >> data;
file << data +1;
file.close();

c++ - fstream and ofstream

What is the difference between:
fstream texfile;
textfile.open("Test.txt");
and
ofstream textfile;
textfile.open("Test.txt");
Are their function the same?
ofstream only has methods for outputting, so for instance if you tried textfile >> whatever it would not compile. fstream can be used for input and output, although what will work depends on the flags you pass to the constructor / open.
std::string s;
std::ofstream ostream("file");
std::fstream stream("file", stream.out);
ostream >> s; // compiler error
stream >> s; // no compiler error, but operation will fail.
The comments have some more great points.
Take a look at their pages on cplusplus.com here and here.
ofstream inherits from ostream. fstream inherits from iostream, which inherits from both istream and stream. Generally ofstream only supports output operations (i.e. textfile << "hello"), while fstream supports both output and input operations but depending on the flags given when opening the file. In your example, the open mode is ios_base::in | ios_base::out by default. The default open mode of ofstream is ios_base::out. Moreover, ios_base::out is always set for ofstream objects (even if explicitly not set in argument mode).
Use ofstream when textfile is for output only, ifstream for input only, fstream for both input and output. This makes your intention more obvious.

fstream input and output position are the same although inherited from istream and ostream

I want to to delete all data in binary files in the range: 10-19.
fstream myFile(f.bin, ios_base::in | ios_base::out | ios_base::app | ios_base::binary);
myFile.seekg(20);
myFile.seekp(10);
myFile << myFile;
myFile.close();
The problem is that internal position is stored in a single place.
Although here: http://www.cplusplus.com/reference/istream/iostream/
it is stated that it inherited from different base classes, and should been stored twice.
I understand I can use 2 different streams. But I am asking how to achieve this with a single stream?
What about using intermediate stream which is not a file stream- to avoid reopening the file again?

fstream >> int failing?

Any idea why the following would fail?
std::fstream i(L"C:/testlog.txt", std::ios::binary | std::ios::in);
int test = 0;
i >> test;
fail() is returning true. The file exists and is opened.
I checked
i._Filebuffer._Myfile._ptr
and it is pointer to a buffer of the file so I don't see why it is failing.
You're opening the file in binary mode. The extraction operators were meant to be used with text files. Simply leave out the std::ios::binary flag to open the file in text mode.
If you actually do have a binary file, use the read() function instead.
Edit: I tested it too, and indeed it seems to work. I got this from CPlusPlus.com, where it says:
In binary files, to input and output data with the extraction and insertion operators (<< and >>) and functions like getline is not efficient, since we do not need to format any data, and data may not use the separation codes used by text files to separate elements (like space, newline, etc...).
Together with the description of ios::binary, which simply states "Consider stream as binary rather than text.", I'm utterly confused now. This answer is turning into a question of its own...
The following:
#include <fstream>
#include <iostream>
using namespace std
int main() {
std::fstream i("int.dat" , std::ios::binary | std::ios::in);
int test = 0;
if ( i >> test ) {
cout << "ok" << endl;
}
}
prints "ok" when given a file containing the characters "123". Please post a similar short test that illustrates your code failing.

C++ fstream << and >> operators with binary data

I've always read and been told that when dealing with binary files that one should use read() and write() as opposed to the << and >> operators as they are meant for use with formatted data. I've also read that it is possible to use them, but it is an advanced topic, which I can't find where anyone dives into and discusses.
I recently saw some code which did the following:
std::ifstream file1("x", ios_base::in | ios_base::binary);
std::ofstream file2("y", ios_base::app | ios_base::binary);
file1 << file2.rdbuf();
When I pointed out the use of the << operator with the binary file, I was told that the rdbuf() call returns a streambuf * and that << overloads the streambuf* and does a direct copy with no formatting and is thus safe.
Is this true and also safe? How about efficiency? Any gotchas? Details would be much appreciated.
Thanks!
Yes (see 27.6.2.5.3/6 where the overload of << for streambuf is described).
It's entirely safe and a reasonable way to copy streams.
Note that it also allows stuff like:
std::ifstream file_in1("x1", ios_base::in | ios_base::binary);
std::ifstream file_in2("x2", ios_base::in | ios_base::binary);
std::ofstream file_out("y", ios_base::app | ios_base::binary);
file_out << file_in1.rdbuf() << "\nand\n" << file_in2.rdbuf();
In § 27.7.3.6.3 of the C++ standard, it's mentioned that
basic_ostream<charT,traits>& operator<<
(basic_streambuf<charT,traits>* sb);
Effects: Behaves as an unformatted output function (as described in 27.7.3.7, paragraph 1).
§ 27.7.3.7 describes "unformatted input" which is basically a binary copy. This means that "unformatted" ostream functions are safe for binary data. The other "unformatted" functions mentioned in the standard that I can find are put, write and (officially) flush.