16

I wrote the following program using VS2008:

#include <fstream>
int main()
{
    std::wofstream fout("myfile");
    fout << L"Հայաստան Россия Österreich Ελλάδα भारत" << std::endl;
}

When I tried to compile it the IDE asked me whether I wanted to save my source file in unicode, I said "yes, please".
Then I run the program, and myfile appeared in my project's folder. I opened it with notepad, the file was empty. I recalled that notepad supported only ASCII data. I opened it with WordPad, it was still empty. Finally the little genius inside me urged me to look at the file size and not surprisingly it was 0 bytes. So I rebuilt and reran the program, to no effect. Finally I decided to ask very intelligent people on StackOverflow as to what I am missing and here I am :)

Edited:

After the abovementioned intelligent people left some comments, I decided to follow their advice and rewrote the program like this:

#include <fstream>
#include <iostream>
int main()
{
    std::wofstream fout("myfile");
    if(!fout.is_open())
    {
        std::cout << "Before: Not open...\n";
    }
    fout << L"Հայաստան Россия Österreich Ελλάδα भारत" << std::endl;
    if(!fout.good())
    {
        std::cout << "After: Not good...\n";
    }
}

Built it. Ran it. And... the console clearly read, to my surprise: "After: Not good...". So I edited my post to provide the new information and started waiting for answers which would explain why this is and what I could do. :)

ST3
  • 8,826
  • 3
  • 68
  • 92
Armen Tsirunyan
  • 130,161
  • 59
  • 324
  • 434

3 Answers3

12

MSVC offers the codecvt_utf8 locale facet for this problem.

#include <codecvt>

// ...  
std::wofstream fout(fileName);
std::locale loc(std::locale::classic(), new std::codecvt_utf8<wchar_t>);
fout.imbue(loc);
DerKuchen
  • 1,840
  • 1
  • 15
  • 15
  • @DerKuchen: fatal error C1083: Cannot open include file: 'codecvt': No such file or directory. – Armen Tsirunyan Oct 16 '10 at 21:23
  • @Armen Tsirunyan: What version of MSVC do you use? At least for MSVC 2010 it works. – DerKuchen Oct 16 '10 at 21:25
  • @DerKuchen: As my post says, I am using MSVC2008. So are you implying I can't do what I want to do with my compiler? :( – Armen Tsirunyan Oct 16 '10 at 21:27
  • 2
    @Armen Tsirunyan: I'm sorry, I overlooked that. I tried it with MSVC2008 and it seems that this version misses the header. – DerKuchen Oct 16 '10 at 21:29
  • I figured out I could download the header, but I can't find it available for download... any ideas if that's possible/legal? OK, whatever I don't care about legal :) – Armen Tsirunyan Oct 16 '10 at 21:36
  • I'm not sure if the header alone is enough, it may need some library/runtime support. It should be available in the MSVC 2010 Express Version: http://www.microsoft.com/express/downloads/#2010-Visual-CPP – DerKuchen Oct 16 '10 at 21:45
  • Solved for me, using VS2010. – IssamTP May 22 '14 at 14:37
8

In Visual studio the output stream is always written in ANSI encoding, and it does not support UTF-8 output.

What is basically need to do is to create a locale class, install into it UTF-8 facet and then imbue it to the fstream.

What happens that code points are not being converted to UTF encoding. So basically this would not work under MSVC as it does not support UTF-8.

This would work under Linux with UTF-8 locale

#include <fstream>
int main()
{
    std::locale::global(std::locale(""));
    std::wofstream fout("myfile");
    fout << L"Հայաստան Россия Österreich Ελλάδα भारत" << std::endl;
}

~ And under windows this would work:

#include <fstream>
int main()
{
    std::locale::global(std::locale("Russian_Russia"));
    std::wofstream fout("myfile");
    fout << L"Россия" << std::endl;
}

As only ANSI encodings are supported by MSVC.

Codecvt facet can be found in some Boost libraries. For example: http://www.boost.org/doc/libs/1_38_0/libs/serialization/doc/codecvt.html

Richard
  • 56,349
  • 34
  • 180
  • 251
Artyom
  • 31,019
  • 21
  • 127
  • 215
0

I found the following code working properly. I am using VS2019.

#include <iostream>
#include <fstream>
#include <codecvt>

int main()
{
    std::wstring str = L"abàdëef€hhhhhhhµa";
    std::wofstream fout(L"C:\\app.log.txt", ios_base::app); //change this to ios_base::in or ios_base::out as per relevance
    std::locale loc(std::locale::classic(), new std::codecvt_utf8<wchar_t>);
    fout.imbue(loc);
    fout << str;
    fout.close();
}
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Nov 10 '21 at 06:28