17

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. :)

9
  • Please feel free to retag my question since I am not entirely sure I got the tags right Commented Oct 16, 2010 at 20:54
  • First, check fout.good() Commented Oct 16, 2010 at 20:56
  • Check to see if fout is valid (it sounds like it but best to check in the code). Commented Oct 16, 2010 at 20:56
  • @Martin: before I write into it or after? Commented Oct 16, 2010 at 20:58
  • @Xirdus: No, don't. The state bits aren't set until after operations. Rather, check is_open. Commented Oct 16, 2010 at 21:08

3 Answers 3

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); 
Sign up to request clarification or add additional context in comments.

7 Comments

@DerKuchen: fatal error C1083: Cannot open include file: 'codecvt': No such file or directory.
@Armen Tsirunyan: What version of MSVC do you use? At least for MSVC 2010 it works.
@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: I'm sorry, I overlooked that. I tried it with MSVC2008 and it seems that this version misses the header.
I figured out I could download the <codecvt> 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 :)
|
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

3 Comments

Thanks a lot. But what if I do want it to print the whole string? Any workaround?
Yes, install utf-8 codecvt facet. There are such ready facets in Boost. Also there is Boost.Locale library, but the last one would be probably overkill.
Is this still the best way with C++14 and VS2015?
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(); } 

1 Comment

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.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.