C++ 在Windows控制台应用程序中输出unicode字符串
嗨,我正试图用iostreams将unicode字符串输出到控制台,但失败了 我发现了这个:这个片段很有效C++ 在Windows控制台应用程序中输出unicode字符串,c++,unicode,iostream,windows-console,C++,Unicode,Iostream,Windows Console,嗨,我正试图用iostreams将unicode字符串输出到控制台,但失败了 我发现了这个:这个片段很有效 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_UTF
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);
但是,我没有找到任何方法可以使用iostreams正确输出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;
我认为没有一个简单的答案。查看,您似乎需要为要输出的字符集设置适当的代码页。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;
}
int-tmain(int-argc,_-TCHAR*argv[]
{
char*locale=setlocale(LC_ALL,“English”);//获取CRT的当前区域设置。
std::locale lollage(locale);
setlocale(LC_ALL,locale);//恢复CRT。
std::wcout.imbue(lollocale);//现在将std::wcout设置为我们从CRT获得的区域设置。
std::wcout最近,我想将unicode从Python流式传输到windows控制台,下面是我需要做的最低要求:
- 您应该将console字体设置为覆盖unicode符号的字体。没有广泛的选择:console属性>字体>Lucida console
- 您应该更改当前控制台代码页:在控制台中运行<代码> CHCP 65001 <代码>,或者使用C++代码< /LI>中的相应方法
- 使用WriteConsoleW写入控制台
浏览一篇关于
此外,在Python中,你不能对默认的SysStdUn进行写写,在这种情况下,你需要用OS来代替它。写(1,二进制字符串)或直接调用Wrror EndoSeCo中的包装器。看起来像C++一样,你也需要这样做。首先,对不起,我可能没有字体,所以我不能测试它。
这里有点可疑
// 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
//据说以下功能正在工作
SetConsoleOutputCP(CP_UTF8);//输出为UTF8格式
wchar_t s[]=L“èèèèèèèèèèèèèèè;
int bufferSize=WideCharToMultiByte(CP_UTF8,0,s,-1,NULL,0,NULL,NULL);
char*m=新字符[bufferSize];
宽图表多字节(CP_UTF8,0,s,-1,m,bufferSize,NULL,NULL);
wprintf(L“%S”,m);//我有一个类似的问题,包含在运行程序之前需要在控制台中执行的gemchcp 65001
可能有一些方法可以通过编程实现,但我不知道它是什么。我在这里使用Visual Studio 2010验证了一个解决方案。通过这个和。诀窍是对\u setmode(…,\u O\u U16TEXT)
解决方案:
#包括
#包括
#包括
int wmain(int argc,wchar_t*argv[])
{
_setmode(_fileno(stdout),_O_16text);
std::wcoutSetConsoleCP()和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);
源代码必须保存为不带BOM(字节顺序标记;签名)的UTF-8。然后,Microsoft编译器cl.exe按原样接受UTF-8字符串。
如果此代码与BOM一起保存,cl.exe会将字符串转码为ANSI(即CP1252),这与CP65001(=UTF-8)不匹配。
将显示字体更改为Lucidia Console,否则UTF-8输出将无法工作
- 类型:
chcp
- 回答:
850
- 类型:
test.exe
- 回答:
tr├尼宁├╝贝尔斯特├Ôäó山
- 类型:
chcp
- 回答:
65001
-此设置已通过SetConsoleCP()
更改,但没有任何有用的效果。
- 类型:
chcp 65001
- 类型:
test.exe
- 回答:
tränenüberströmt™代码>-现在一切正常。
测试:德语Windows XP SP3在Windows控制台中正确显示西欧字符
长话短说:
使用chcp
查找适合您的代码页。在我的例子中,它是西欧的chcp 28591
可选择将其设为默认值:REG ADD HKCU\Console/v CodePage/t REG\u DWORD/d 28591
发现历史
Java也有类似的问题,这只是表面现象,因为它涉及到发送到控制台的日志行;但仍然很烦人
Java应用程序的输出应该是UTF-8格式,并且在eclipse的控制台中正确显示。但在windows控制台中,它只显示ASCII框绘图字符:Inicializaci├│n
和艺术├“culos
而不是Inicialización
和artículos
我偶然发现并混合了一些答案,找到了适合我的解决方案。解决方案是使用支持UNICODE的字体(如ConsoleAS
或lucida console
)更改控制台使用的代码页和。您可以在Windows cosole的系统菜单中选择的字体:
通过以下任一方法启动控制台:
Win+R
然后键入cmd
并点击Return
键
- 按
Win
键,键入cmd
,然后按return
键
通过以下任一方法打开系统菜单:
- 单击左上角的图标
- 点击
Alt+Space
组合键
然后选择“Default”以更改所有后续控制台窗口的行为
单击“字体”选项卡
选择Consolas
或Lucida console
单击OK
关于代码页,对于一次性情况,您可以使用命令chcp
完成,然后您必须调查哪个代码页适合您的字符集。几个答案建议使用UTF-8代码页,即65001,但该代码页不适合我的西班牙语字符
建议使用批处理脚本以交互方式从列表中选择所需的代码页。在那里,我找到了我需要的ISO-8859-1代码页:28591。因此,您可以执行
chcp 28591
在每次执行应用程序之前。您可以在中检查哪个代码页适合您
// 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;
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);
chcp 28591
REG ADD HKCU\Console /v CodePage /t REG_DWORD /d 28591
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;
int wmain(int argc, wchar_t* argv[])
SetConsoleOutputCP(CP_UTF8);
SetConsoleCP(CP_UTF8);
CONSOLE_FONT_INFOEX fontInfo;
// ... configure fontInfo
SetCurrentConsoleFontEx(hConsole, false, &fontInfo);
char* a = setlocale(LC_ALL, "chinese");
std::wcout << L"你好" << std::endl;
#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;
}
#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
#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;
}
std::wstring x = L"\0\001日本ABC\0DE\0F\0GYou can use the open-source {fmt} library to portably print Unicode text, including on Windows, for example:
#include <fmt/core.h>
int main() {
fmt::print("èéøÞǽлљΣæča");
}
èéøÞǽлљΣæča
├и├й├╕├Ю╟╜╨╗╤Щ╬г├ж─Нa
#include <boost/nowide/iostream.hpp>
#include <char8_t-remediation.h>
int main()
{
using boost::nowide::cout;
cout << U8("¡Hola!") << std::endl;
}
#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;