Преобразование UTF-8 в UCS-2 с библиотекой icu

В настоящее время я работаю и сталкиваюсь с проблемой преобразования строки UTF-8 в строку UCS-2 с помощью библиотеки icu. В библиотеке есть несколько способов сделать это, но пока ни один из них не работает, но, учитывая популярность этой библиотеки, я предполагаю, что делаю что-то не так.

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

В настоящее время используется строка utf-8 просто «ĩ».

Для простоты я буду представлять строку, используемую как uniString в этом коде.

UErrorCode resultCode = U_ZERO_ERROR;

UConverter* m_pConv = ucnv_open("ISO-8859-1", &resultCode);

// Change the callback to error out instead of the default            
const void* oldContext;
UConverterFromUCallback oldFromAction;
UConverterToUCallback oldToAction;
ucnv_setFromUCallBack(m_pConv, UCNV_FROM_U_CALLBACK_STOP, NULL, &oldFromAction, &oldContext, &resultCode);
ucnv_setToUCallBack(m_pConv, UCNV_TO_U_CALLBACK_STOP, NULL, &oldToAction, &oldContext, &resultCode);

int32_t outputLength = 0;
int bodySize = uniString.length();
int targetSize = bodySize * 4;
char* target = new char[targetSize];                       

printf("Body: %s\n", uniString.c_str());
if (U_SUCCESS(resultCode))
{
    // outputLength = ucnv_convert("ISO-8859-1", "UTF-8", target, targetSize, uniString.c_str(), bodySize, &resultCode);
    outputLength = ucnv_fromAlgorithmic(m_pConv, UCNV_UTF8, target, targetSize, uniString.c_str(),
        uniString.length(), &resultCode);
    ucnv_close(m_pConv);
}
printf("ISO-8859-1 DGF just tried to convert '%s' to '%s' with error '%i' and length '%i'", uniString.c_str(), 
    outputLength ? target : "invalid_char", resultCode, outputLength);

if (resultCode == U_INVALID_CHAR_FOUND || resultCode == U_ILLEGAL_CHAR_FOUND || resultCode == U_TRUNCATED_CHAR_FOUND)
{
    if (resultCode == U_INVALID_CHAR_FOUND)
    {
        printf("Unmapped input character, cannot be converted to Latin1");                    

        m_pConv = ucnv_open("UCS-2", &resultCode);
        if (U_SUCCESS(resultCode))
        {
            // outputLength = ucnv_convert("UCS-2", "UTF-8", target, targetSize, uniString.c_str(), bodySize, &resultCode);
            outputLength = ucnv_fromAlgorithmic(m_pConv, UCNV_UTF8, target, targetSize, uniString.c_str(),
                uniString.length(), &resultCode);
            ucnv_close(m_pConv);
        }

        printf("UCS-2 DGF just tried to convert '%s' to '%s' with error '%i' and length '%i'", uniString.c_str(), 
            outputLength ? target : "invalid_char", resultCode, outputLength);

        if (U_SUCCESS(resultCode))
        {
            pdus = SegmentText(target, pText, SEGMENT_SIZE_UNICODE_MAX, true);
        }
    }
    else
    {
        printf("DecodeText(): Text contents does not appear to be valid UTF-8");
    }
}
else
{
    printf("DecodeText(): Text successfully converted to Latin1");
    std::string newBody(target, outputLength);
    pdus = SegmentText(newBody, pPdu, SEGMENT_SIZE_MAX);
}

Проблема в том, что функция ucnv_fromAlgorithmic выдает ошибку U_INVALID_CHAR_FOUND для преобразования ucs-2. Это имеет смысл для попытки ISO-8859-1, но не для ucs-2.

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

Итак, вопрос в том, есть ли у кого-нибудь опыт работы с этими функциями и что-то не так, или есть что-то неправильное в предположении о преобразовании для этого персонажа?


person MumblesCrzy    schedule 05.03.2014    source источник
comment
@KevinPanko Обновлено с проблемой и вопросом. Спасибо.   -  person MumblesCrzy    schedule 06.03.2014


Ответы (1)


Вам нужно сбросить resultCode на U_ZERO_ERROR перед вызовом ucnv_open. Цитата из руководства:

«Функции ICU, которые принимают ссылку (C++) или указатель (C) на UErrorCode, сначала проверяют if(U_FAILURE(errorCode)) { возвращаются немедленно; } так что в цепочке таких функций первая, которая устанавливает код ошибки, вызывает следующие, чтобы не выполнять никаких операций"

person Per Johansson    schedule 05.03.2014
comment
Большое спасибо за это. - person MumblesCrzy; 06.03.2014