I trying to understand std::basic_ofstream
. I started with this:
#include <fstream>
int main() {
std::ofstream test_stream("data.txt");
int my_int = 12;
double my_double = 26.8;
test_stream << my_int << " " << my_double;
}
When you open data.txt
in Notepad, you see
12 26.8
This told me that <<
formatted the output and stored the output as char
s ( cppreference ). Indeed, the size of data.txt
was 7 bytes.
I wanted to output my data as raw bits to prevent conversion to strings. I found I could do that with write
:
test_stream.write((char*) & my_int, 4);
test_stream.write((char*) & my_double, 4);
This functionally does what I want/expected. data.txt
will appear as 12 bytes that are the little endian, binary representation of 12 and 26.8. However, I was hoping for some nicer notation. I tried the put
member function, but that only outputs 1 byte of the int
.
I then considered the possibility of changing basic_ofstream
's character type to int
. My hope was that I could do something like this
int main() {
std::basic_ofstream<int> test_stream("data.txt");
int my_int = 123412431;
test_stream.put(my_int);
}
or this
int main() {
std::basic_ofstream<int> test_stream("data.txt");
int my_int = 123412431;
test_stream << my_int;
}
The first gives only 1 byte output Ï
. The second gives an error. I assumed that the point of std::basic_ofstream<int>
would be to overload put
to transfer int
s.
So what is the difference between std::basic_ofstream<int>
and std::basic_ofstream<char>
? Is there a way to make std::basic_ofstream<int>
do what I want? (for clarity: what I want is the functionality of the write
example with put
or <<
.)
int
is not a character type. You cannot use it as template argument to std::basic_ostream
.
(Technically it may be supported as implementation-defined character type, but I don't think any implementation actually does that.)
Only char
(corresponding to std::ostream
) and wchar_t
(corresponding to std::wostream
) are generally supported.
Your approach of outputting the object representation with std::ofstream
is correct and how it should be done, except that you should use reinterpret_cast<const char*>
instead of (char*)
and that you should use sizeof(/*variable name*/)
instead of a magic number. Both of these help avoid mistakes.
You can wrap that in a function to have nicer notation which doesn't require repeating the variable name twice:
template<typename T>
std::ostream& print_object_representation(std::ostream& o, const T& t) {
// Use `std::addressof(t)` instead of `&t` to
// correctly handle classes with overloaded `operator&`
o.write(reinterpret_cast<const char*>(&t), sizeof(t));
return o;
}
//...
print_object_representation(test_stream, my_double);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.