utfcpp и Win32 широкий API

Хорошо ли / безопасно / возможно использовать крошечную библиотеку utfcpp для преобразования всего, что я получаю от широкого Windows API (FindFirstFileW и тому подобное), в действительное представление UTF8 с использованием utf16to8?

Я хотел бы использовать UTF8 для внутреннего использования, но у меня возникают проблемы с получением правильного вывода (через wcout после другого преобразования или простой cout). Нормальные символы ASCII работают, конечно, но они запутались.

Или есть более легкая альтернатива?

Спасибо!

ОБНОВЛЕНИЕ: Благодаря Гансу (ниже), теперь у меня есть простое преобразование UTF8<->UTF16 через Windows API. Работает двухстороннее преобразование, но в строке UTF8 из строки UTF16 есть некоторые дополнительные символы, которые могут вызвать у меня проблемы позже...). Я поделюсь этим здесь из чистого дружелюбия:))

// UTF16 -> UTF8 conversion
std::string toUTF8( const std::wstring &input )
{
    // get length
    int length = WideCharToMultiByte( CP_UTF8, NULL,
                                      input.c_str(), input.size(),
                                      NULL, 0,
                                      NULL, NULL );
    if( !(length > 0) )
        return std::string();
    else
    {
        std::string result;
        result.resize( length );

        if( WideCharToMultiByte( CP_UTF8, NULL,
                                 input.c_str(), input.size(),
                                 &result[0], result.size(),
                                 NULL, NULL ) > 0 )
            return result;
        else
            throw std::runtime_error( "Failure to execute toUTF8: conversion failed." );
    }
}
// UTF8 -> UTF16 conversion
std::wstring toUTF16( const std::string &input )
{
    // get length
    int length = MultiByteToWideChar( CP_UTF8, NULL,
                                      input.c_str(), input.size(),
                                      NULL, 0 );
    if( !(length > 0) )
        return std::wstring();
    else
    {
        std::wstring result;
        result.resize( length );

        if( MultiByteToWideChar(CP_UTF8, NULL,
                                input.c_str(), input.size(),
                                &result[0], result.size()) > 0 )
            return result;
        else
            throw std::runtime_error( "Failure to execute toUTF16: conversion failed." );
    }
}

2 ответа

Решение

В Win32 API уже есть функция для этого, WideCharToMultiByte() с CodePage = CP_UTF8. Спасает вас от необходимости полагаться на другую библиотеку.

Обычно вы не можете использовать результат с wcout. Его вывод идет на консоль, он использует 8-битную OEM-кодировку по устаревшим причинам. Вы можете изменить кодовую страницу с помощью SetConsoleCP(), 65001 - это кодовая страница для UTF-8 (CP_UTF8).

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

Почему вы хотите использовать UTF8 внутри? Вы работаете с таким количеством текста, что использование UTF16 создаст необоснованные требования к памяти? Даже если бы это было так, вам, вероятно, все равно лучше использовать широкие символы и решать проблемы с памятью каким-либо другим способом (используя дисковый кеш, лучшие алгоритмы или структуры данных).

Ваш код будет намного чище и проще в использовании, если использовать внутренние символы, встроенные в Win32 API, и выполнять преобразования UTF8 только при чтении или записи нужных данных (например, файлов XML или API REST).

Ваша проблема также может возникать в тот момент, когда вы выводите выходные данные на консоль, см. Вывод строк Unicode в консольном приложении Windows.

Наконец, я не использовал библиотеку utfcpp, но преобразования в UTF8 довольно тривиальны для выполнения с использованием Win32. WideCharToMultiByte а также MultiByteToWideChar с CP_UTF8 как кодовая страница. Лично я бы делал одноразовое преобразование и работал с текстом в UTF16, пока не пришло время выводить или переносить его в UTF8, если это необходимо.

Другие вопросы по тегам