在Windows控制台应用程序中输出unicode字符串

时间:2010-03-22 12:15:57

标签: c++ unicode iostream windows-console

您好我尝试使用 iostreams 将unicode字符串输出到控制台并失败。

我发现了这个:Using unicode font in c++ console app并且此代码段有效。

SetConsoleOutputCP(CP_UTF8);
wchar_t s[] = L"èéøÞǽлљΣæča";
int bufferSize = WideCharToMultiByte(CP_UTF8, 0, s, -1, NULL, 0, NULL, NULL);
char* m = new char[bufferSize]; 
WideCharToMultiByte(CP_UTF8, 0, s, -1, m, bufferSize, NULL, NULL);
wprintf(L"%S", m);

但是,我没有找到任何方法来使用iostream正确输出unicode。有什么建议吗?

这不起作用:

SetConsoleOutputCP(CP_UTF8);
utf8_locale = locale(old_locale,new boost::program_options::detail::utf8_codecvt_facet());
wcout.imbue(utf8_locale);
wcout << L"¡Hola!" << endl;

修改 我找不到任何其他解决方案,而不是在流中包装此代码段。 希望,有人有更好的想法。

//Unicode output for a Windows console 
ostream &operator-(ostream &stream, const wchar_t *s) 
{ 
    int bufSize = WideCharToMultiByte(CP_UTF8, 0, s, -1, NULL, 0, NULL, NULL);
    char *buf = new char[bufSize];
    WideCharToMultiByte(CP_UTF8, 0, s, -1, buf, bufSize, NULL, NULL);
    wprintf(L"%S", buf);
    delete[] buf; 
    return stream; 
} 

ostream &operator-(ostream &stream, const wstring &s) 
{ 
    stream - s.c_str();
    return stream; 
} 

15 个答案:

答案 0 :(得分:82)

我已使用Visual Studio 2010验证了解决方案。通过此MSDN articleMSDN blog post。诀窍是对_setmode(..., _O_U16TEXT)的晦涩调用。

<强>解决方案:

#include <iostream>
#include <io.h>
#include <fcntl.h>

int wmain(int argc, wchar_t* argv[])
{
    _setmode(_fileno(stdout), _O_U16TEXT);
    std::wcout << L"Testing unicode -- English -- Ελληνικά -- Español." << std::endl;
}

<强>截图:

Unicode in console

答案 1 :(得分:6)

Unicode Hello World in Chinese

Here is a Hello World in Chinese. Actually it is just "Hello". I tested this on Windows 10, but I think it might work since Windows Vista. Before Windows Vista it will be hard, if you want a programmatic solution, instead of configuring the console / registry etc. Maybe have a look here if you really need to do this on Windows 7: Change console Font Windows 7

I dont want to claim this is the only solution, but this is what worked for me.

Outline

  1. Unicode project setup
  2. Set the console codepage to unicode
  3. Find and use a font that supports the characters you want to display
  4. Use the locale of the language you want to display
  5. Use the wide character output i.e. std::wcout

1 Project Setup

I am using Visual Studio 2017 CE. I created a blank console app. The default settings are alright. But if you experience problems or you use a different ide you might want to check these:

In your project properties find configuration properties -> General -> Project Defaults -> Character Set. It should be "Use Unicode Character Set" not "Multi-Byte". This will define _UNICODE and UNICODE preprocessor macros for you.

int wmain(int argc, wchar_t* argv[])

Also I think we should use wmain function instead of main. They both work, but in a unicode environment wmain may be more convenient.

Also my source files are UTF-16-LE encoded, which seems to be the default in Visual Studio 2017.

2. Console Codepage

This is quite obvious. We need the unicode codepage in the console. If you want to check your default codepage, just open a console and type chcp withou any arguments. We have to change it to 65001, which is the UTF-8 codepage. Windows Codepage Identifiers There is a preprocessor macro for that codepage: CP_UTF8. I needed to set both, the input and output codepage. When I omitted either one, the output was incorrect.

SetConsoleOutputCP(CP_UTF8);
SetConsoleCP(CP_UTF8);

You might also want to check the boolean return values of those functions.

3. Choose a Font

Until yet I didnt find a console font that supports every character. So I had to choose one. If you want to output characters which are partly only available in one font and partly in another font, then I believe it is impossible to find a solution. Only maybe if there is a font out there that supports every character. But also I didnt look into how to install a font.

I think it is not possible to use two different fonts in the same console window at the same time.

How to find a compatible font? Open your console, go to the properties of the console window by clicking on the icon in the upper left of the window. Go to the fonts tab and choose a font and click ok. Then try to enter your characters in the console window. Repeat this until you find a font you can work with. Then note down the name of the font.

Also you can change the size of the font in the properties window. If you found a size you are happy with, note down the size values that are displayed in the properties window in the section "selected font". It will show width and height in pixels.

To actually set the font programmatically you use:

CONSOLE_FONT_INFOEX fontInfo;
// ... configure fontInfo
SetCurrentConsoleFontEx(hConsole, false, &fontInfo);

See my example at the end of this answer for details. Or look it up in the fine manual: SetCurrentConsoleFont. This function only exists since Windows Vista.

4. Set the locale

You will need to set the locale to the locale of the language which characters you want to print.

char* a = setlocale(LC_ALL, "chinese");

The return value is interesting. It will contain a string to describe exactly wich locale was chosen. Just give it a try :-) I tested with chinese and german. More info: setlocale

5. Use wide character output

Not much to say here. If you want to output wide characters, use this for example:

std::wcout << L"你好" << std::endl;

Oh, and dont forget the L prefix for wide characters! And if you type literal unicode characters like this in the source file, the source file must be unicode encoded. Like the default in Visual Studio is UTF-16-LE. Or maybe use notepad++ and set the encoding to UCS-2 LE BOM.

Example

Finally I put it all together as an example:

#include <Windows.h>
#include <iostream>
#include <io.h>
#include <fcntl.h>
#include <locale.h>
#include <wincon.h>

int wmain(int argc, wchar_t* argv[])
{
    SetConsoleTitle(L"My Console Window - 你好");
    HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);

    char* a = setlocale(LC_ALL, "chinese");
    SetConsoleOutputCP(CP_UTF8);
    SetConsoleCP(CP_UTF8);

    CONSOLE_FONT_INFOEX fontInfo;
    fontInfo.cbSize = sizeof(fontInfo);
    fontInfo.FontFamily = 54;
    fontInfo.FontWeight = 400;
    fontInfo.nFont = 0;
    const wchar_t myFont[] = L"KaiTi";
    fontInfo.dwFontSize = { 18, 41 };
    std::copy(myFont, myFont + (sizeof(myFont) / sizeof(wchar_t)), fontInfo.FaceName);

    SetCurrentConsoleFontEx(hConsole, false, &fontInfo);

    std::wcout << L"Hello World!" << std::endl;
    std::wcout << L"你好!" << std::endl;
    return 0;
}

Cheers !

答案 2 :(得分:3)

wcout必须将区域设置设置为与CRT不同。以下是它的修复方法:

int _tmain(int argc, _TCHAR* argv[])
{
    char* locale = setlocale(LC_ALL, "English"); // Get the CRT's current locale.
    std::locale lollocale(locale);
    setlocale(LC_ALL, locale); // Restore the CRT.
    std::wcout.imbue(lollocale); // Now set the std::wcout to have the locale that we got from the CRT.
    std::wcout << L"¡Hola!";
    std::cin.get();
    return 0;
}

我刚试过它,它在这里显示的字符串绝对正常。

答案 3 :(得分:2)

SetConsoleCP()和 chcp 不一样!

获取此程序片段:

SetConsoleCP(65001)  // 65001 = UTF-8
static const char s[]="tränenüberströmt™\n";
DWORD slen=lstrlen(s);
WriteConsoleA(GetStdHandle(STD_OUTPUT_HANDLE),s,slen,&slen,NULL);

源代码必须保存为UTF-8 ,无 BOM(字节顺序标记;签名)。然后,Microsoft编译器 cl.exe 按原样获取UTF-8字符串 如果此代码使用 BOM保存,则cl.exe将字符串转码为ANSI(即CP1252),这与CP65001(= UTF-8)不匹配。

将显示字体更改为 Lucidia Console ,否则UTF-8输出将无法正常工作。

  • 类型:chcp
  • 答案:850
  • 输入:test.exe
  • 答案:tr├ñnen├╝berstr├ÂmtÔäó
  • 输入:chcp
  • 答案:65001 - 此设置已由SetConsoleCP()更改,但没有任何有用的效果。
  • 输入:chcp 65001
  • 输入:test.exe
  • 答案:tränenüberströmt™ - 现在一切正常。

测试:德国Windows XP SP3

答案 4 :(得分:1)

您可以使用 the open-source {fmt} library 可移植地打印 Unicode 文本,包括在 Windows 上,例如:

#include <fmt/core.h>

int main() {
  fmt::print("èéøÞǽлљΣæča");
}

输出:

èéøÞǽлљΣæča

这需要使用 MSVC 中的 /utf-8 编译器选项进行编译。

我不建议使用 wcout,因为它不可移植,而且在没有额外努力的情况下甚至无法在 Windows 上运行,例如:

std::wcout << L"èéøÞǽлљΣæča";

将打印:

├и├й├╕├Ю╟╜╨╗╤Щ╬г├ж─Нa

在俄语 Windows 中(ACP 1251,控制台 CP 866)。

免责声明:我是 {fmt} 的作者。

答案 5 :(得分:1)

如果您正在寻找可移植的解决方案,但不幸的是,它仍然不是 C++20 标准的一部分,我可以推荐 nowide 库。它来自 standalone 或作为 boost 的一部分。您会发现许多标准对应物在那里使用或发出 utf-8 编码的 char。是的,char,而不是 char8_t(目前)。随意使用 char8_t-remediation utilitieschar8_t 解释为 char,如果您的程序已经运行它们。

请求的代码片段如下所示:

#include <boost/nowide/iostream.hpp>
#include <char8_t-remediation.h>

int main()
{
    using boost::nowide::cout;

    cout << U8("¡Hola!") << std::endl;
}

注意:请注意 streams orientation issue。在我的回答上下文中的简短建议是:只使用 nowide 流用于输入/输出和 utf-8 编码数据

答案 6 :(得分:0)

我认为没有一个简单的答案。查看Console Code PagesSetConsoleCP Function,您似乎需要为要输出的字符集设置合适的代码页。

答案 7 :(得分:0)

Recenly我想将unicode从Python流式传输到Windows控制台,这是我需要做的最小值:

  • 您应该将控制台字体设置为覆盖unicode符号的字体。没有广泛的选择:控制台属性&gt;字体&gt; Lucida Console
  • 您应该更改当前的控制台代码页:在控制台中运行chcp 65001或使用C ++代码中的相应方法
  • 使用WriteConsoleW
  • 写入控制台

查看有关java unicode on windows console

的有趣文章

此外,在Python中你无法写入默认的sys.stdout,在这种情况下,你需要用os.write(1,binarystring)代替它,或者直接调用WriteConsoleW的包装器。看起来像在C ++中你需要做同样的事情。

答案 8 :(得分:0)

首先,抱歉我可能没有所需的字体,所以我还不能测试它。

这里的东西看起来有点可疑

// the following is said to be working
SetConsoleOutputCP(CP_UTF8); // output is in UTF8
wchar_t s[] = L"èéøÞǽлљΣæča";
int bufferSize = WideCharToMultiByte(CP_UTF8, 0, s, -1, NULL, 0, NULL, NULL);
char* m = new char[bufferSize]; 
WideCharToMultiByte(CP_UTF8, 0, s, -1, m, bufferSize, NULL, NULL);
wprintf(L"%S", m); // <-- upper case %S in wprintf() is used for MultiByte/utf-8
                   //     lower case %s in wprintf() is used for WideChar
printf("%s", m); // <-- does this work as well? try it to verify my assumption

,而

// the following is said to have problem
SetConsoleOutputCP(CP_UTF8);
utf8_locale = locale(old_locale,
                     new boost::program_options::detail::utf8_codecvt_facet());
wcout.imbue(utf8_locale);
wcout << L"¡Hola!" << endl; // <-- you are passing wide char.
// have you tried passing the multibyte equivalent by converting to utf8 first?
int bufferSize = WideCharToMultiByte(CP_UTF8, 0, s, -1, NULL, 0, NULL, NULL);
char* m = new char[bufferSize]; 
WideCharToMultiByte(CP_UTF8, 0, s, -1, m, bufferSize, NULL, NULL);
cout << m << endl;

怎么样

// without setting locale to UTF8, you pass WideChars
wcout << L"¡Hola!" << endl;
// set locale to UTF8 and use cout
SetConsoleOutputCP(CP_UTF8);
cout << utf8_encoded_by_converting_using_WideCharToMultiByte << endl;

答案 9 :(得分:0)

mswcrt和io流存在一些问题。

  1. Trick _setmode(_fileno(stdout),_ O_U16TEXT);仅适用于MS VC ++而非MinGW-GCC。此外,有时它会导致崩溃,具体取决于Windows配置。
  2. 用于UTF-8的SetConsoleCP(65001)。在许多多字节字符方案中可能会失败,但UTF-16LE
  3. 总是可以的
  4. 您需要在应用程序退出时恢复预览控制台代码页。
  5. Windows控制台支持UNICODE,其中ReadConsole和WriteConsole功能采用UTF-16LE模式。背景效果 - 在这种情况下管道不起作用。即myapp.exe&gt;&gt; ret.log带来0字节的ret.log文件。如果你对这个事实没问题,可以试试我的库。

    const char* umessage = "Hello!\nПривет!\nПривіт!\nΧαιρετίσματα!\nHelló!\nHallå!\n";
    
    ...
    #include <console.hpp>
    #include <ios>
    ...
    
    std::ostream& cout = io::console::out_stream();
    cout << umessage
    << 1234567890ull << '\n'
    << 123456.78e+09 << '\n'
    << 12356.789e+10L << '\n'
    << std::hex << 0xCAFEBABE
    << std::endl;
    

    Library会将您的UTF-8自动转换为UTF-16LE,并使用WriteConsole将其写入控制台。以及错误和输入流。 另一个图书馆的好处 - 颜色。

    示例应用上的链接: https://github.com/incoder1/IO/tree/master/examples/iostreams

    图书馆主页: https://github.com/incoder1/IO

    Screenshot:

答案 10 :(得分:0)

默认编码为:

  
      
  • Windows UTF-16。
  •   
  • Linux UTF-8。
  •   
  • MacOS UTF-8。
  •   

我的解决方案步骤,包括空字符\ 0(避免被截断)。在Windows.h标头上不使用函数:

  
      
  1. 添加宏以检测平台。
  2.   
#if defined (_WIN32) 
#define WINDOWSLIB 1

#elif defined (__ANDROID__) || defined(ANDROID)//Android
#define ANDROIDLIB 1

#elif defined (__APPLE__)//iOS, Mac OS
#define MACOSLIB 1

#elif defined (__LINUX__) || defined(__gnu_linux__) || defined(__linux__)//_Ubuntu - Fedora - Centos - RedHat
#define LINUXLIB 1
#endif
  
      
  1. 创建转换函数std :: w 到std :: string的字符串,反之亦然。
  2.   
#include <locale>
#include <iostream>
#include <string>
#ifdef WINDOWSLIB
#include <Windows.h>
#endif

using namespace std::literals::string_literals;

// Convert std::wstring to std::string
std::string WidestringToString(const std::wstring& wstr, const std::string& locale)
{
    if (wstr.empty())
    {
        return std::string();
    }
    size_t pos;
    size_t begin = 0;
    std::string ret;
    size_t  size;
#ifdef WINDOWSLIB
    _locale_t lc = _create_locale(LC_ALL, locale.c_str());
    pos = wstr.find(static_cast<wchar_t>(0), begin);
    while (pos != std::wstring::npos && begin < wstr.length())
    {
        std::wstring segment = std::wstring(&wstr[begin], pos - begin);
        _wcstombs_s_l(&size, nullptr, 0, &segment[0], _TRUNCATE, lc);
        std::string converted = std::string(size, 0);
        _wcstombs_s_l(&size, &converted[0], size, &segment[0], _TRUNCATE, lc);
        ret.append(converted);
        begin = pos + 1;
        pos = wstr.find(static_cast<wchar_t>(0), begin);
    }
    if (begin <= wstr.length()) {
        std::wstring segment = std::wstring(&wstr[begin], wstr.length() - begin);
        _wcstombs_s_l(&size, nullptr, 0, &segment[0], _TRUNCATE, lc);
        std::string converted = std::string(size, 0);
        _wcstombs_s_l(&size, &converted[0], size, &segment[0], _TRUNCATE, lc);
        converted.resize(size - 1);
        ret.append(converted);
    }
    _free_locale(lc);
#elif defined LINUXLIB
    std::string currentLocale = setlocale(LC_ALL, nullptr);
    setlocale(LC_ALL, locale.c_str());
    pos = wstr.find(static_cast<wchar_t>(0), begin);
    while (pos != std::wstring::npos && begin < wstr.length())
    {
        std::wstring segment = std::wstring(&wstr[begin], pos - begin);
        size = wcstombs(nullptr, segment.c_str(), 0);
        std::string converted = std::string(size, 0);
        wcstombs(&converted[0], segment.c_str(), converted.size());
        ret.append(converted);
        ret.append({ 0 });
        begin = pos + 1;
        pos = wstr.find(static_cast<wchar_t>(0), begin);
    }
    if (begin <= wstr.length()) {
        std::wstring segment = std::wstring(&wstr[begin], wstr.length() - begin);
        size = wcstombs(nullptr, segment.c_str(), 0);
        std::string converted = std::string(size, 0);
        wcstombs(&converted[0], segment.c_str(), converted.size());
        ret.append(converted);
    }
    setlocale(LC_ALL, currentLocale.c_str());
#elif defined MACOSLIB
#endif

    return ret;
}

// Convert std::string to std::wstring
std::wstring StringToWideString(const std::string& str, const std::string& locale)
{
    if (str.empty())
    {
        return std::wstring();
    }

    size_t pos;
    size_t begin = 0;
    std::wstring ret;
    size_t  size;

#ifdef WINDOWSLIB
    _locale_t lc = _create_locale(LC_ALL, locale.c_str());
    pos = str.find(static_cast<char>(0), begin);
    while (pos != std::string::npos) {
        std::string segment = std::string(&str[begin], pos - begin);
        std::wstring converted = std::wstring(segment.size() + 1, 0);
        _mbstowcs_s_l(&size, &converted[0], converted.size(), &segment[0], _TRUNCATE, lc);
        converted.resize(size - 1);
        ret.append(converted);
        ret.append({ 0 });
        begin = pos + 1;
        pos = str.find(static_cast<char>(0), begin);
    }
    if (begin < str.length()) {
        std::string segment = std::string(&str[begin], str.length() - begin);
        std::wstring converted = std::wstring(segment.size() + 1, 0);
        _mbstowcs_s_l(&size, &converted[0], converted.size(), &segment[0], _TRUNCATE, lc);
        converted.resize(size - 1);
        ret.append(converted);
    }
    _free_locale(lc);
#elif defined LINUXLIB
    std::string currentLocale = setlocale(LC_ALL, nullptr);
    setlocale(LC_ALL, locale.c_str());
    pos = str.find(static_cast<char>(0), begin);
    while (pos != std::string::npos) {
        std::string segment = std::string(&str[begin], pos - begin);
        std::wstring converted = std::wstring(segment.size(), 0);
        size = mbstowcs(&converted[0], &segment[0], converted.size());
        converted.resize(size);
        ret.append(converted);
        ret.append({ 0 });
        begin = pos + 1;
        pos = str.find(static_cast<char>(0), begin);
    }
    if (begin < str.length()) {
        std::string segment = std::string(&str[begin], str.length() - begin);
        std::wstring converted = std::wstring(segment.size(), 0);
        size = mbstowcs(&converted[0], &segment[0], converted.size());
        converted.resize(size);
        ret.append(converted);
    }
    setlocale(LC_ALL, currentLocale.c_str());
#elif defined MACOSLIB
#endif

    return ret;
}
  
      
  1. 打印std :: string。   选中RawString Suffix
  2.   

Linux代码。使用std :: cout直接打印std :: string。
如果您有std :: wstring。
1.转换为std :: string。
2.使用std :: cout打印。

std::wstring x = L"\0\001日本ABC\0DE\0F\0G\0"s;
std::string result = WidestringToString(x, "en_US.UTF-8");
std::cout << "RESULT=" << result << std::endl;
std::cout << "RESULT_SIZE=" << result.size() << std::endl;

在Windows上,如果您需要打印unicode。我们需要使用WriteConsole从std :: wstring或std :: string打印Unicode字符。

void WriteUnicodeLine(const std::string& s)
{
#ifdef WINDOWSLIB
    WriteUnicode(s);
    std::cout << std::endl;
#elif defined LINUXLIB
    std::cout << s << std::endl;
#elif defined MACOSLIB
#endif
}

void WriteUnicode(const std::string& s)
{

#ifdef WINDOWSLIB
    std::wstring unicode = Insane::String::Strings::StringToWideString(s);
    WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), unicode.c_str(), static_cast<DWORD>(unicode.length()), nullptr, nullptr);
#elif defined LINUXLIB
    std::cout << s;
#elif defined MACOSLIB
#endif


}

void WriteUnicodeLineW(const std::wstring& ws)
{

#ifdef WINDOWSLIB
    WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), ws.c_str(), static_cast<DWORD>(ws.length()), nullptr, nullptr);
    std::cout << std::endl;
#elif defined LINUXLIB
    std::cout << String::Strings::WidestringToString(ws)<<std::endl;
#elif defined MACOSLIB
#endif


}

void WriteUnicodeW(const std::wstring& ws)
{

#ifdef WINDOWSLIB
    WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), ws.c_str(), static_cast<DWORD>(ws.length()), nullptr, nullptr);
#elif defined LINUXLIB
    std::cout << String::Strings::WidestringToString(ws);
#elif defined MACOSLIB
#endif

}

Windows代码。使用WriteLineUnicode或WriteUnicode函数。相同的代码可用于Linux。

std::wstring x = L"\0\001日本ABC\0DE\0F\0G\0"s;
std::string result = WidestringToString(x, "en_US.UTF-8");
WriteLineUnicode(u8"RESULT" + result);
WriteLineUnicode(u8"RESULT_SIZE" + std::to_string(result.size()));

最后在Windows上。您需要在控制台中对Unicode字符提供强大而完整的支持。 我推荐ConEmu并设置为default terminal on Windows

在Microsoft Visual Studio和Jetbrains Clion上进行测试。

  
      
  • 在带有VC ++的Microsoft Visual Studio 2017上测试; std = c ++ 17。 (Windows项目)
  •   
  • 使用g ++在Microsoft Visual Studio 2017上测试; std = c ++ 17。 (Linux项目)
  •   
  • 使用g ++在Jetbrains Clion 2018.3上进行测试; std = c ++ 17。 (Linux工具链/远程)
  •   

质量检查

  

。为什么不使用<codecvt>标头函数和类?    A。弃用Removed or deprecated features不能在VC ++上构建,但在g ++上则没有问题。我更喜欢0警告和头痛。

     

Q。 Windows上的wstring是interchan。
   A。弃用Removed or deprecated features不能在VC ++上构建,但在g ++上则没有问题。我更喜欢0警告和头痛。

     

。std :: wstring是跨平台的吗?
   A。号std :: wstring使用wchar_t元素。在Windows上,wchar_t的大小为2个字节,每个字符以UTF-16单位存储,如果字符大于U + FFFF,则该字符以称为代理对的两个UTF-16单位(2个wchar_t元素)表示。在Linux上,wchar_t的大小为4个字节,每个字符存储在一个wchar_t元素中,不需要代理对。选中Standard data types on UNIX, Linux, and Windows

     

问。 std :: string是跨平台的吗?
   A。是。 std :: string使用char元素。保证char类型在所有编译器中都是相同的字节大小。 char类型的大小为1个字节。选中Standard data types on UNIX, Linux, and Windows

答案 11 :(得分:0)

在具有英国区域设置的 Win10 下从 VS2017 运行控制台应用程序需要我:

  1. 设置VS2017工具>环境>字体和颜色>字体:例如'Lucida'
  2. 使用编码“Unicode(带签名的 UTF-8) - 代码页 650001”保存 C++ 源文件,这样您就可以在没有编译器警告的情况下输入重音字符 L"âéïôù",同时避免在任何地方使用双字节字符
  3. 使用配置属性编译 > 常规 > 字符集 > “使用多字节..”和配置属性 > C/C++ > 所有选项 > 附加选项 > “/utf-8”标志
  4. #include
  5. 执行一个晦涩的 '_setmode(_fileno(stdout), _O_WTEXT);'一次在应用程序开始时
  6. 忘记'cout <<...;'并且只使用 'wcout << ... ;'

请注意,Win7 上的 VS2015 需要“SetConsoleOutputCP(65001);”并允许通过 wcout 和 cout 混合输出。

答案 12 :(得分:0)

就我而言,我正在阅读 UTF-8 文件并打印到 Console,我发现 wifstream 效果很好,即使在 Visual Studio 调试器中也能正确显示 UTF-8 单词(我正在阅读繁体中文),来自this post

#include <sstream>
#include <fstream>
#include <codecvt>

std::wstring readFile(const char* filename)
{
    std::wifstream wif(filename);
    wif.imbue(std::locale(std::locale::empty(), new std::codecvt_utf8<wchar_t>));
    std::wstringstream wss;
    wss << wif.rdbuf();
    return wss.str();
}

//  usage
std::wstring wstr2;
wstr2 = readFile("C:\\yourUtf8File.txt");
wcout << wstr2;

答案 13 :(得分:-1)

我遇到了类似的问题,Output Unicode to console Using C++, in Windows包含在运行程序之前需要在控制台中执行的chcp 65001宝石。

可能有某种方式以编程方式执行此操作,但我不知道它是什么。

答案 14 :(得分:-1)

在Windows控制台中正确显示西欧字符

长话短说:

  1. 使用chcp查找适合您的代码页。就我而言,西欧是chcp 28591
  2. 可选择将其设为默认值:REG ADD HKCU\Console /v CodePage /t REG_DWORD /d 28591
  3. 发现的历史

    我遇到了类似的问题,使用Java。它只是化妆品,因为它涉及发送到控制台的日志行;但它仍然很烦人。

    我们的Java应用程序的输出应该是UTF-8,它在eclipse的控制台中正确显示。但是在Windows控制台中,它只显示ASCII框图形字符:Inicializaci├│nart├¡culos而不是Inicializaciónartículos

    我偶然发现a related question并混合了一些答案,以找到适合我的解决方案。解决方案是使用支持UNICODE的字体(如consolaslucida console)更改控制台 使用的代码页。您可以在Windows cosole的系统菜单中选择的字体:

    1. 通过任何一个启动控制台
      • Win + R然后输入cmd并点击Return键。
      • 点击Win键,然后输入cmd,然后输入return键。
    2. 按任意一个打开系统菜单
      • 点击左上角的图标
      • 点击Alt + Space组合键
    3. 然后选择&#34;默认&#34;更改所有后续控制台窗口的行为
    4. 点击&#34;字体&#34;标签
    5. 选择ConsolasLucida console
    6. 点击OK
    7. 关于代码页,对于一次性案例,您可以使用命令chcp完成它,然后您必须调查哪个代码页对于您的字符集是正确的。几个答案建议使用UTF-8代码页,即65001,但该代码页对我的西班牙语字符不起作用。

      Another answer建议使用批处理脚本以交互方式从列表中选择所需的代码页。在那里我找到了ISO-8859-1的代码页我需要:28591。所以你可以执行

      chcp 28591
      
      每次执行您的应用程序之前

      。您可以在Code Page Identifiers MSDN page

      中查看哪个代码页适合您

      Yet another answer表示如何将所选代码页保留为Windows控制台的默认代码。它涉及更改注册表,因此请考虑自己警告您可能会使用此解决方案来破坏您的计算机。

      REG ADD HKCU\Console /v CodePage /t REG_DWORD /d 28591
      

      这将使用HKCU \ Console注册表项中的CodePage数据创建28591值。这确实对我有用。

      请注意,HKCU(&#34; HKEY_CURRENT_USER&#34;)仅适用于当前用户。如果要为该计算机中的所有用户更改它,您需要使用regedit实用程序并查找/创建相应的Console密钥(可能您必须创建Console

      中的HKEY_USERS\.DEFAULT