It's reading fine, it's just not writing.
std::wcout << (wchar_t)fin.get() << "\n";
Unfortunately std::wcout
doesn't actually reliably get Unicode to a terminal.
Although the Windows terminal works natively in UTF-16 code units, std::wcout
is still defined in purely byte-based terms. It converts its wide input down to bytes using the locale-specific default encoding before writing to the good old Unicode-ignorant byte stdout stream (which could be a natively-bytes file redirection as well as a natively-Unicode terminal output, after all).
So std::wcout
ends up being just as limited under Windows as all the other byte IO interfaces, restricted to characters in the current code page. Your code page is probably 932, where character 单
U+5355 doesn't exist, so trying to write it breaks the stream.
Setting the current code page to 65001 in an attempt to get the same UTF-8 output that all other modern platforms prefer doesn't quite work due to assorted multibyte char-counting bugs in the basic C runtime. MS have left this broken for many multiple versions so expect UTF-8 to remain a second-class citizen under Windows.
Some alternatives:
Use the Win32 WriteConsoleW
API instead of stdlib interfaces. (Requires care to handle possible output redirection, and if you need your project to be cross-platform compatible.)
Use _setmode
with _O_U16TEXT
to change the output stream to UTF-16-encoded bytes. See example in this question. It seems not all interfaces necessarily work in this mode; you're probably in for trouble if you try to use the byte interfaces at the same time.
Output explicitly UTF-8-encoded bytes and require Windows console users to just put up with the mojibake and missing glyphs that result.
It is a shame this story is still so miserable.