Как распечатать UTF-8 из консольного приложения С++ в Windows
Для консольного приложения С++, скомпилированного с Visual Studio 2008 на английском языке Windows (XP, Vista или 7). Можно ли распечатать на консоли и правильно отобразить японский язык с кодировкой UTF-8 с помощью cout или wcout?
Ответы
Ответ 1
Консоль Windows использует OEM-страницу кода по умолчанию для вывода вывода.
Чтобы изменить кодовую страницу на Unicode, введите chcp 65001
в консоли или попробуйте программно изменить кодовую страницу с помощью SetConsoleOutputCP
.
Обратите внимание, что вам, вероятно, придется изменить шрифт консоли на тот, у которого есть глифы в диапазоне Unicode.
Ответ 2
Вот статья MVP Майкла Каплана о том, как правильно выводить UTF-16 через консоль. Вы можете конвертировать UTF-8 в UTF-16 и выводить их.
Ответ 3
Я никогда не пытался настроить кодовую страницу консоли на UTF8 (не уверен, почему это не сработает... консоль может обрабатывать другие многобайтовые кодовые страницы просто отлично), но есть пара функции для поиска: SetConsoleCP и SetConsoleOutputCP.
Возможно, вам также понадобится убедиться, что вы используете консольный шрифт, который способен отображать ваши персонажи. Там SetCurrentConsoleFontEx функция, но она доступна только в Vista и выше.
Надеюсь, что это поможет.
Ответ 4
Это должно работать:
#include <cstdio>
#include <windows.h>
#pragma execution_character_set( "utf-8" )
int main()
{
SetConsoleOutputCP( 65001 );
printf( "Testing unicode -- English -- Ελληνικά -- Español -- Русский. aäbcdefghijklmnoöpqrsßtuüvwxyz\n" );
}
Не знаю, влияет ли это на что-либо, но исходный файл сохраняется как Unicode (UTF-8 с сигнатурой) - Codepage 65001 в ФАЙЛ → Расширенные параметры сохранения....
Проект → Свойства → Свойства конфигурации → Общие → Набор символов установлено значение Использовать набор символов Unicode.
Некоторые говорят, что вам нужно изменить консольный шрифт на Lucida Console, но на моей стороне он отображается как с Consolas, так и с Lucida Console.
Ответ 5
В консоли запуска приложения установлено значение по умолчанию для OEM437 CP.
Я пытался вывести текст Unicode в stdout, где консоль переключилась на перевод UTF8 _setmode (_fileno (stdout), _O_U8TEXT); и до сих пор не повезло на экране даже с шрифтом Lucida TT.
Если консоль была перенаправлена в файл, был создан файл UTF8.
Наконец мне повезло. Я добавил одну строку "info.FontFamily = FF_DONTCARE;" и он работает сейчас.
Надейтесь, что это поможет вам.
void SetLucidaFont()
{
HANDLE StdOut = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_FONT_INFOEX info;
memset(&info, 0, sizeof(CONSOLE_FONT_INFOEX));
info.cbSize = sizeof(CONSOLE_FONT_INFOEX); // prevents err=87 below
if (GetCurrentConsoleFontEx(StdOut, FALSE, &info))
{
info.FontFamily = FF_DONTCARE;
info.dwFontSize.X = 0; // leave X as zero
info.dwFontSize.Y = 14;
info.FontWeight = 400;
_tcscpy_s(info.FaceName, L"Lucida Console");
if (SetCurrentConsoleFontEx(StdOut, FALSE, &info))
{
}
}
}
Ответ 6
Только для дополнительной информации:
"ANSI" относится к окнам-125x, которые используются для приложений win32, в то время как "OEM" относится к кодовой странице, используемой консольными/MS-DOS-приложениями.
Текущие активные кодовые страницы могут быть получены с помощью функций GetOEMCP() и GetACP().
Чтобы вывести что-то правильно на консоль, вы должны:
-
убедитесь, что текущая кодовая страница OEM поддерживает символы, которые вы хотите вывести
(при необходимости используйте SetConsoleOutputCP, чтобы установить его правильно)
-
преобразовать строку из текущего кода ANSI (win32) в кодовую страницу OEM-сервера консоли
Вот несколько утилит для этого:
// Convert a UTF-16 string (16-bit) to an OEM string (8-bit)
#define UNICODEtoOEM(str) WCHARtoCHAR(str, CP_OEMCP)
// Convert an OEM string (8-bit) to a UTF-16 string (16-bit)
#define OEMtoUNICODE(str) CHARtoWCHAR(str, CP_OEMCP)
// Convert an ANSI string (8-bit) to a UTF-16 string (16-bit)
#define ANSItoUNICODE(str) CHARtoWCHAR(str, CP_ACP)
// Convert a UTF-16 string (16-bit) to an ANSI string (8-bit)
#define UNICODEtoANSI(str) WCHARtoCHAR(str, CP_ACP)
/* Convert a single/multi-byte string to a UTF-16 string (16-bit).
We take advantage of the MultiByteToWideChar function that allows to specify the charset of the input string.
*/
LPWSTR CHARtoWCHAR(LPSTR str, UINT codePage) {
size_t len = strlen(str) + 1;
int size_needed = MultiByteToWideChar(codePage, 0, str, len, NULL, 0);
LPWSTR wstr = (LPWSTR) LocalAlloc(LPTR, sizeof(WCHAR) * size_needed);
MultiByteToWideChar(codePage, 0, str, len, wstr, size_needed);
return wstr;
}
/* Convert a UTF-16 string (16-bit) to a single/multi-byte string.
We take advantage of the WideCharToMultiByte function that allows to specify the charset of the output string.
*/
LPSTR WCHARtoCHAR(LPWSTR wstr, UINT codePage) {
size_t len = wcslen(wstr) + 1;
int size_needed = WideCharToMultiByte(codePage, 0, wstr, len, NULL, 0, NULL, NULL);
LPSTR str = (LPSTR) LocalAlloc(LPTR, sizeof(CHAR) * size_needed );
WideCharToMultiByte(codePage, 0, wstr, len, str, size_needed, NULL, NULL);
return str;
}
Ответ 7
В консоли введите chcp 65001
, чтобы изменить кодовую страницу на UTF-8.