Выводить строки юникода в консольное приложение Windows - PullRequest
68 голосов
/ 22 марта 2010

Привет! Я пытался вывести строку Unicode на консоль с iostreams и не смог.

Я нашел это: Использование шрифта Unicode в консольном приложении c ++ , и этот фрагмент работает.

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. Есть предложения?

Это не работает:

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

EDIT Я не мог найти другого решения, кроме как обернуть этот фрагмент в поток. Надеюсь, у кого-то есть идеи получше.

//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; 
} 

Ответы [ 11 ]

81 голосов
/ 29 января 2012

Я проверил решение здесь, используя Visual Studio 2010. С помощью этой статьи MSDN и MSDN * .Трюк - неясный вызов _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

5 голосов
/ 25 марта 2018

Unicode Hello World на китайском

Вот Hello World на китайском языке. На самом деле это просто «Привет». Я проверил это на Windows 10, но я думаю, что это может работать с Windows Vista. До Windows Vista будет сложно, если вам нужно программное решение, вместо настройки консоли / реестра и т. Д. Может быть, посмотрите здесь, если вам действительно нужно сделать это в Windows 7: Изменить шрифт консоли Windows 7

Я не хочу утверждать, что это единственное решение, но это то, что сработало для меня.

Outline

  1. Настройка проекта Unicode
  2. Установить кодовую страницу консоли в Unicode
  3. Найдите и используйте шрифт, который поддерживает символы, которые вы хотите отобразить
  4. Используйте язык, который вы хотите отобразить
  5. Используйте вывод широких символов, т.е. std::wcout

1 Настройка проекта

Я использую Visual Studio 2017 CE. Я создал пустое консольное приложение. Настройки по умолчанию в порядке. Но если у вас возникли проблемы или вы используете другой идеал, вы можете проверить это:

В свойствах вашего проекта найдите свойства конфигурации -> Общие -> Стандартные настройки проекта -> Набор символов. Это должно быть «Использовать набор символов Юникода», а не «Многобайтовый». Это определит макросы препроцессора _UNICODE и UNICODE для вас.

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

Также я думаю, что мы должны использовать функцию wmain вместо main. Они оба работают, но в среде Unicode wmain может быть более удобным.

Также мои исходные файлы имеют кодировку UTF-16-LE, которая, по-видимому, используется по умолчанию в Visual Studio 2017.

2. Кодовая страница консоли

Это совершенно очевидно. Нам нужна кодовая страница Unicode в консоли. Если вы хотите проверить кодовую страницу по умолчанию, просто откройте консоль и введите chcp без аргументов. Мы должны изменить его на 65001, который является кодовой страницей UTF-8. Идентификаторы кодовой страницы Windows Для этой кодовой страницы есть макрос препроцессора: CP_UTF8. Мне нужно было установить и кодовую страницу ввода и вывода. Когда я пропустил любой из них, вывод был неправильным.

SetConsoleOutputCP(CP_UTF8);
SetConsoleCP(CP_UTF8);

Возможно, вы также захотите проверить логические возвращаемые значения этих функций.

3. Выберите шрифт

Пока я не нашел консольный шрифт, который поддерживает каждый символ. Поэтому мне пришлось выбрать один. Если вы хотите вывести символы, которые частично доступны только одним шрифтом и частично другим шрифтом, то я считаю, что найти решение невозможно. Только возможно, если есть шрифт, который поддерживает каждый символ. Но я также не смотрел, как установить шрифт.

Я думаю, что невозможно использовать два разных шрифта в одном и том же окне консоли одновременно.

Как найти совместимый шрифт? Откройте консоль, перейдите в свойства окна консоли, нажав на значок в левом верхнем углу окна. Перейдите на вкладку «Шрифты», выберите шрифт и нажмите «ОК». Затем попробуйте ввести свои символы в окне консоли. Повторяйте это, пока не найдете шрифт, с которым вы можете работать. Затем запишите название шрифта.

Также вы можете изменить размер шрифта в окне свойств. Если вы нашли нужный вам размер, запишите значения размеров, которые отображаются в окне свойств в разделе «выбранный шрифт». Он покажет ширину и высоту в пикселях.

Чтобы фактически установить шрифт программно, вы используете:

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

См. Мой пример в конце этого ответа для деталей. Или посмотрите это в прекрасном руководстве: SetCurrentConsoleFont . Эта функция существует только с Windows Vista.

4. Установите локаль

Вам нужно будет установить локаль на язык, на котором вы хотите печатать символы.

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

Возвращаемое значение интересно. Он будет содержать строку для точного описания выбранной локали. Просто попробуйте :-) Я тестировал с chinese и german. Больше информации: setlocale

5. Использовать вывод широких символов

Не так много, чтобы сказать здесь.Если вы хотите выводить широкие символы, используйте это, например:

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

Да, и не забывайте префикс L для широких символов! И если вы набираете буквальные символы Юникода, подобные этим, в исходном файле, исходный файл должен быть в кодировке Юникод. Как по умолчанию в Visual Studio UTF-16-LE. Или, может быть, используйте notepad ++ и установите кодировку на UCS-2 LE BOM.

* 1 089 * Пример

Наконец, я собрал все это в качестве примера:

#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;
}

Ура!

3 голосов
/ 01 апреля 2010

У 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;
}

Я только что проверил, и здесь строка отображается абсолютно нормально.

2 голосов
/ 17 июля 2012

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 (Byte Order Mark; Signature). Затем компилятор 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

0 голосов
/ 22 февраля 2019

Кодировка по умолчанию включена:

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

Мое решение Шаги, включают нулевые символы \ 0 (избегать усеченных). Без использования функций в заголовке windows.h:

  1. Добавьте макросы для обнаружения платформы.
#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 или наоборот.
#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 .

Код Linux. Напечатайте непосредственно std :: string, используя std :: cout.
Если у вас есть 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.

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. Вам нужна мощная и полная поддержка символов Юникода в консоли. Я рекомендую ConEmu и установить в качестве терминала по умолчанию в Windows .

Тест на Microsoft Visual Studio и Jetbrains Clion.

  • Проверено на Microsoft Visual Studio 2017 с VC ++; станд = C ++ 17. (Проект Windows)
  • Проверено на Microsoft Visual Studio 2017 с g ++; станд = C ++ 17. (Проект Linux)
  • Проверено на Jetbrains Clion 2018.3 с g ++; станд = C ++ 17. (Linux Toolchain / Remote)

QA

Q. Почему бы вам не использовать <codecvt> функции и классы заголовков?.
A. Устаревшие Удаленные или устаревшие функции Невозможно построить на VC ++, но без проблем на g ++. Я предпочитаю 0 предупреждений и головных болей.

Q. строки в Windows чередуются.
A. Устаревшие Удаленные или устаревшие функции Невозможно построить на VC ++, но без проблем на g ++. Я предпочитаю 0 предупреждений и головных болей.

Q. std :: wstring является кроссплатформенным?
A. No. std :: wstring использует элементы wchar_t. В Windows размер wchar_t составляет 2 байта, каждый символ сохраняется в единицах UTF-16, если символ больше, чем U + FFFF, символ представляется в двух единицах UTF-16 (2 элемента wchar_t), называемых суррогатными парами. В Linux размер wchar_t составляет 4 байта, каждый символ хранится в одном элементе wchar_t, без суррогатных пар. Проверьте Стандартные типы данных в UNIX, Linux и Windows .

Q. std :: string является кроссплатформенным?
A. Да. std :: string использует элементы char. Гарантируется, что тип char одинакового размера во всех компиляторах. Размер шрифта составляет 1 байт. Проверьте Стандартные типы данных в UNIX, Linux и Windows .

0 голосов
/ 01 марта 2018

Есть несколько проблем с потоками mswcrt и io.

  1. Трюк _setmode (_fileno (stdout), _O_U16TEXT); работает только для MS VC ++, а не MinGW-GCC. Более того, иногда это приводит к сбоям в зависимости от конфигурации Windows.
  2. SetConsoleCP (65001) для UTF-8. Может не работать во многих многобайтовых символьных сценариях, но всегда подходит для UTF-16LE
  3. Вам необходимо восстановить кодовую страницу консоли предварительного просмотра при выходе из приложения.

Консоль Windows поддерживает UNICODE с функциями ReadConsole и WriteConsole в режиме UTF-16LE. Фоновый эффект - в этом случае трубопровод не будет работать. То есть myapp.exe >> 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;

Библиотека автоматически преобразует ваш UTF-8 в UTF-16LE и записывает его в консоль с помощью WriteConsole. Как и есть ошибки и входные потоки. Еще одно преимущество библиотеки - цвета.

Ссылка на пример приложения: https://github.com/incoder1/IO/tree/master/examples/iostreams

Домашняя страница библиотеки: https://github.com/incoder1/IO

Скриншот:

0 голосов
/ 20 сентября 2017

Правильное отображение западноевропейских символов в консоли Windows

Короче говоря:

  1. используйте chcp, чтобы найти, какая кодовая страница работает для вас. В моем случае это было chcp 28591 для Западной Европы.
  2. при желании сделать его по умолчанию: REG ADD HKCU\Console /v CodePage /t REG_DWORD /d 28591

История открытия

У меня была похожая проблема с Java. Это просто косметика, так как включает в себя строки журнала, отправленные на консоль; но это все еще раздражает.

Вывод из нашего Java-приложения должен быть в UTF-8, и он правильно отображается в консоли eclipse. Но в консоли Windows просто отображаются символы рисования ASCII-полей: Inicializaci├│n и art├¡culos вместо Inicialización и artículos.

Я наткнулся на связанный вопрос и смешал некоторые ответы, чтобы найти решение, которое работало для меня. Решением является изменение кодовой страницы, используемой консолью и , с использованием шрифта, поддерживающего UNICODE (например, consolas или lucida console). Шрифт, который вы можете выбрать в системном меню Windows cosole:

  1. Запустить консоль любым из
    • Win + R затем введите cmd и нажмите клавишу Return.
    • Нажмите клавишу Win и введите cmd, а затем клавишу return.
  2. Открыть системное меню любым из
    • щелкните значок в верхнем левом углу
    • Нажмите комбинацию клавиш Alt + Space
  3. затем выберите «По умолчанию», чтобы изменить поведение всех последующих окон консоли
  4. нажмите вкладку «Шрифт»
  5. Выберите Consolas или Lucida console
  6. Нажмите OK

Что касается кодовой страницы, для одноразового случая вы можете сделать это с помощью команды chcp, а затем вам нужно выяснить, какая кодовая страница подходит для вашего набора символов. В нескольких ответах была предложена кодовая страница UTF-8, то есть 65001, но эта кодовая страница не работала для моих испанских символов.

Другой ответ предложил пакетный скрипт для интерактивного выбора нужной кодовой страницы из списка. Там я нашел нужную кодовую страницу ISO-8859-1: 28591. Так что вы можете выполнить

chcp 28591

перед каждым исполнением вашей заявки. Вы можете проверить, какая кодовая страница вам подходит, на странице MSDN Идентификаторы кодовой страницы .

В еще одном ответе указано, как сохранить выбранную кодовую страницу по умолчанию для консоли Windows. Это включает в себя изменение реестра, поэтому считайте себя предупрежденным о том, что с помощью этого решения вы можете заблокировать свой компьютер.

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

Это создает значение CodePage с данными 28591 внутри раздела реестра HKCU \ Console. И это сработало для меня.

Обратите внимание, что HKCU ("HKEY_CURRENT_USER") только для текущего пользователя. Если вы хотите изменить его для всех пользователей этого компьютера, вам нужно использовать утилиту regedit и найти / создать соответствующий ключ Console (возможно, вам придется создать ключ Console внутри HKEY_USERS\.DEFAULT)

0 голосов
/ 07 февраля 2011

У меня была похожая проблема, Вывод Unicode на консоль. Используя C ++, в Windows содержит гем, который нужно сделать chcp 65001 в консоли перед запуском вашей программы.

Может быть какой-то способ сделать это программно, но я не знаю, что это такое.

0 голосов
/ 05 апреля 2010

Во-первых, извините, у меня, вероятно, нет необходимых шрифтов, поэтому я пока не могу его проверить.

Здесь что-то выглядит немного подозрительно

// 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;
0 голосов
/ 01 апреля 2010

Недавно я хотел транслировать Unicode из Python на консоль Windows, и вот минимум, который мне нужно было сделать:

  • Вы должны установить консольный шрифт на тот, который покрывает символы Юникода. Выбор не широк: Свойства консоли> Шрифт> Lucida Console
  • Вы должны изменить текущую кодовую страницу консоли: запустите chcp 65001 в консоли или используйте соответствующий метод в коде C ++
  • запись в консоль с использованием WriteConsoleW

Просмотрите интересную статью о Java Unicode на консоли Windows

Кроме того, в Python вы не можете записать в sys.stdout по умолчанию в этом случае, вам нужно будет заменить его чем-то, используя os.write (1, binarystring) или прямой вызов оболочки вокруг WriteConsoleW. Похоже, что в C ++ вам нужно будет сделать то же самое.

...