When trying to compile this code:
std::fstream file("file.name", std::ios::out | std::ios::binary);
uint8_t buf[BUFSIZE];
//Fill the buffer, etc...
file.write(buf, BUFSIZE);
compiler will give me warning about oh-not-so-healthy conversion from unsigned char
to char
in call to write()
. As std::fstream
is in fact just a typedef for std::basic_fstream<char>
, one could think that using std::basic_fstream<uint8_t>
instead would allow them to compile above code without warning, as write()
expects pointer of template type.
This works, of course, but another problem pops out. Even though this code compiles perfectly fine:
std::basic_fstream<uint8_t> file("file.name", std::ios::out | std::ios::binary);
uint8_t buf[BUFSIZE];
//Fill the buffer, etc...
file.write(buf, BUFSIZE);
it will now fail on call to write()
, even though previous version was working (disregard compiler warnings). It took me a while to pinpoint where exception is thrown from in standard C++ library code, but I still don't really understand what's the case here. It looks like std::basic_fstream
uses a few character coding mechanism, and since there is one defined for char
but none for unsigned char
, the file stream fails silently when trying to use "wrong" character data type... That's how I see it, at least.
But that's also what I don't understand. There is no need for any character encoding. I don't even open file in text mode, I want to deal with binary data. That's why I use arrays of type uint8_t
, not char, it feels more natural to use this data type rather than plain old char
. But before I either decide to give up on uint8_t
data type and just accept working with char
buffers, or start using arrays of custom byte
datatype defined as char
, I'd like to ask two questions:
- What exactly is that mechanism that stops me from using unsigned character datatype? Is it really something related to character encoding, or does it serve some other purpose? Why file stream works fine with signed character data types, but not for unsigned ones?
- Assuming that I still would want to use
std::basic_fstream<uint8_t>
, regardless how (un)reasonable it is - is there any way to achieve that?