Re: wcout, VS2008 and UTF-16
Stephan T. Lavavej [MSFT] wrote:
http://blogs.msdn.com/michkap/archive/2008/03/18/8306597.aspx
Stephan T. Lavavej
Visual C++ Libraries Developer
Hooray, hooray!
And thus we insert the missing magical incantation:
_setmode( _fileno(stdout), _O_U16TEXT );
Note that setting up a correct global std locale with
std::locale newloc(std::locale(), new NullCodecvt());
std::locale::global( newloc );
is still necessary. imbue is not necessary.
Only problem now seems to be that this breaks output via cout!
_setmode( _fileno(stdout), _O_U16TEXT );
cout << "TEST";
=> Dbg assert failed: Expression:
( (_Stream->_flag & _IOSTRG) || ( fn = _fileno(_Stream), (
(_textmode_safe(fn) == __IOINFO_TM__ANSI) && !_tm_unicode_safe(fn))))
Bah. I guess this will have to be fixed by changing the codecvt for
char->char as well ... (or whatever)
cheers,
Martin
"Martin T." <0xCDCDCDCD@gmx.at> wrote in message
news:h5ncrg$vsf$1@news.eternal-september.org...
Greetings.
I'm am currently trying to output wchar_t (== UTF-16) to the windows
console. (The console can display UTF_16 just fine if you change the
font to lucida console - easiest verified with adding a filename with
some greek or cyrillic characters in it and calling dir)
Now, my problem is, that the default wcout stream on windows will
convert wchar_t characters to multibyte.
One can overcome this by adding codecvt like described here:
http://www.ddj.com/cpp/184403638;jsessionid=ADO5UI2ASFTGBQE1GHOSKHWATMY32JVN?pgno=1
However, this only works for binary streams.
The reason that it does not work with wcout is that
basic_filebuf<wchar_t, ..> , on which wcout is based will use
fputwc(..) internally. This function will still try to convert the
wchar_t to multibyte unless the stream is opened in binary mode.
So ... is it possible at all to get wcout to send full UTF-16 to the
console?
thanks,
Martin
Test code:
main.cpp
########
#include "stdafx.h"
#include <stdexcept>
#include <iostream>
#include <fstream>
#include <locale>
using std::codecvt ;
typedef codecvt < wchar_t , char , mbstate_t > NullCodecvtBase ;
class NullCodecvt : public NullCodecvtBase
{
public:
typedef wchar_t elem_t;
typedef char outp_t;
typedef mbstate_t state_t;
explicit NullCodecvt(size_t r=0 ) : NullCodecvtBase(r) { }
protected:
virtual result do_in(state_t& /* conversion state */,
const outp_t* /* begin convert */,
const outp_t* /* end convert */,
const outp_t*& /* next convert */,
elem_t* /* begin converted */,
elem_t* /* end converted */,
elem_t*& /* next converted */) const {
return noconv ;
}
virtual result do_out(state_t& ,
const elem_t* ,
const elem_t* ,
const elem_t*& ,
outp_t* ,
elem_t* ,
outp_t*& ) const {
return noconv ;
}
virtual result do_unshift(state_t& ,
outp_t* ,
outp_t* ,
outp_t*& ) const {
return noconv ;
}
virtual int do_length(state_t& ,
const outp_t* _F1,
const outp_t* _L1,
size_t _N2) const _THROW0() {
return (_N2 < (size_t)(_L1 - _F1)) ? _N2 : _L1 - _F1 ;
}
virtual bool do_always_noconv() const _THROW0() {
return true ;
}
virtual int do_max_length() const _THROW0() {
return 2 ;
}
virtual int do_encoding() const _THROW0() {
return 2 ;
}
};
int main()
{
using namespace std;
try {
// --- init locale ---
const char* locale_id = "german_Germany";
setlocale(LC_ALL, locale_id); // Need to set C locale for fputwc
conversions
std::locale newloc(std::locale(locale_id), new NullCodecvt());
std::locale::global( newloc );
// --- try with wofstream ---
wofstream f;
f.exceptions( ios::badbit | ios::failbit | ios::eofbit );
f.imbue( newloc );
// wchar_t output requires binary output !! (otherwise fputwc fails to
write non-basic wchar_t characters)
f.open("testuni.txt", ios_base::out | ios_base::binary);
// Output works just fine on a Latin1 Windows (e.g. german)
// (But note that we need to supply \r\n for a binary file)
f << L"aAbB ... ???? ... ? ? ? ...\r\n";
f << L"\u03C9 (greek omega) \r\n";
f.close();
// --- try with wcout ---
wcout.exceptions( ios::badbit | ios::failbit | ios::eofbit );
wcout.imbue( newloc );
wcout << L"aAbB ... ???? ... ? ? ? ...\n"; // Works just fine on
(Latin1 charset)
wcout << L"\u03C9 (greek omega) \n"; // Will set badbit, since fputwc
fails
} catch(std::exception const& e) {
cerr << "X!: " << e.what() << endl;
return 1;
}
return 0;
}