C++/ofstream and setf
Expert: Ralph McArdell - 3/31/2008
Question
hello
i have the following question for you
i want to change the flags of a ofstream variable
for example
ofstream writebinary;
writebinary.open("text.txt");
writebinary.setf(ios::binary | ios::app);
but when i compile the program it says that there is
no matching function for setf()
how can i change the flag of a ofstream variable
thanks
AnswerThat is because there is not. Or possibly there is not.
The std::ios_base::setf functions take parameters of type std::ios_base::fmtflags not std::ios_base::openmode, which are the flag types you are trying to use with setf.
Note: The derivation graph for std::ofstream is as follows:
std::ios_base<---std::basic_ios<><---std::basic_ostream<><---std::basic_ofstream<>
Where: B<---D means B is a base class of D (or D is derived from B)
std::ofstream is a specialisation of the std::basic_ofstream<> class template for narrow char based streams.
Likewise std::ios is a specialisation of the basic_ios<> class template for narrow char based streams.
The std::ios_base::fmtflags and std::ios_base::openmode types are typedef type aliases to integer types (the ISO standard C++ document calls them "bitmask types") and so could possibly be aliases to the same type (e.g. unsigned int) but not necessarily. For example on a typical compiler for 32-bit systems std::ios_base::fmtflags could be an alias for unsigned int and std::ios_base::openmode an alias for unsigned char as there are (in the ISO C++ standard) 18 defined format flag values and only 6 open mode values, viz:
namespace std
{
class ios_base
{
public:
// ...
typedef T1 fmtflags;
static const fmtflags boolalpha;
static const fmtflags dec;
static const fmtflags fixed;
static const fmtflags hex;
static const fmtflags internal;
static const fmtflags left;
static const fmtflags oct;
static const fmtflags right;
static const fmtflags scientific;
static const fmtflags showbase;
static const fmtflags showpoint;
static const fmtflags showpos;
static const fmtflags skipws;
static const fmtflags unitbuf;
static const fmtflags uppercase;
static const fmtflags adjustfield;
static const fmtflags basefield;
static const fmtflags floatfield;
// ...
typedef T3 openmode;
static const openmode app;
static const openmode ate;
static const openmode binary;
static const openmode in;
static const openmode out;
static const openmode trunc;
// ...
fmtflags flags() const;
fmtflags flags(fmtflags fmtfl);
fmtflags setf(fmtflags fmtfl);
fmtflags setf(fmtflags fmtfl, fmtflags mask);
void unsetf(fmtflags mask);
// ...
};
}
The above is taken from the 1998-09-01 ISO/IEC 14882 C++ standard document and shows _just_ the relevant parts of the std::ios_base base class definition. Note that the exact types of T1 and T3 that std::ios_base::fmtflags and std::ios_base::openmode are aliases for are _not_ specified; it is left up to each implementation to use suitable types.
The reason you cannot change the open mode of the file stream is that these mode flags apply to how the file is _opened_. Hence once opened that is how you have to use the stream with the file. You cannot just change a flag and get read and well as or instead of write access to a file. A file will either be truncated or will not as part of opening the file - adding a flag to alter this behaviour after the request to open would be some what after the fact.
I can see however that the case for specifying whether to perform end of line translation or not (as controlled by the binary open mode flag) only at file open time could be seen as a little more tenuous. However as a file will generally either be processed as text (i.e. lines, using native end of line character sequences), or as just a sequence of bytes (i.e. binary) then again it makes sense to specify it up front when opening the file.
Note also that the ios::binary flag has no effect on systems such as UNIX and Linux where the end of line character sequence is the same as that used by C and C++ - i.e. just a newline ('\n') character.
If you wish to specify the open mode flags then you do it by passing a second parameter with the required open mode flags bits set after the file pathname value either in the relevant constructor or in a call to open:
ofstream writebinary("text.txt", ios::binary | ios::app);
or:
ofstream writebinary;
writebinary.open("text.txt", ios::binary | ios::app);
I suggest you get yourself a decent reference on C++ IOStreams. For the whole of the C++ standard library and not just the IOStream library I use "The C++ Standard Library A Tutorial and Reference" by Nicolai M. Josuttis. For more focus on C++ IOStreams and locales I use "Standard C++ IOStreams and Locales" by Angelika Langer and Klaus Kreft.
Hope this helps.