繁体   English   中英

如何在 C++ Linux 中使用 ICU 库将 UnicodeString 转换为 windows-1251?

[英]How to convert UnicodeString to windows-1251 using ICU library in c++ Linux?

我有这段代码,它将 UTF-8 字符串转换为 Unicode:

#include <unicode/unistr.h>
//included other header files

int main(int argc, char** argv) {
    std::string s("some string");
        // convert std::string to ICU's UnicodeString
        UnicodeString ucs = UnicodeString::fromUTF8(StringPiece(s.c_str()));

        // convert UnicodeString to std::wstring
        std::wstring ws;
        for (int i = 0; i < ucs.length(); ++i)
            ws += static_cast<wchar_t>(ucs[i]);

        std::wcout << ws;
}

我不明白如何将此 UnicodeString 转换为 windows-1251 (cp1251)。 我应该在 Linux 中使用哪个函数来执行此操作?

ucnv.h使用ICU的转换函数(请参阅ICU文档中的转换>使用转换器 ):

#include <memory>
#include <unicode/ucnv.h>
bool convertTo1251(std::vector<UChar> const & input, std::vector<char> & output)
{
    UErrorCode status = U_ZERO_ERROR;
    UConverter *pConvert = ucnv_open("windows-1251", &status);
    if (status)
    {
        printf("Failed to obtain char set converter: %d\r\n", status);
        return false;
    }
    std::shared_ptr<UConverter> cnv(pConvert, ucnv_close);

    UChar const * pwszBegin = &input[0], *pwszEnd = pwszBegin + input.size();
    output.resize(input.size());

    char *pszBegin = &output[0], *pszEnd = pszBegin + input.size();

    ucnv_fromUnicode(pConvert, &pszBegin, pszEnd, &pwszBegin, pwszEnd, nullptr, true, &status);
    if (status)
    {
        // deal with error
        return false;
    }
    return true;
}

您可以从这里使用独立功能:

#define NONS (0x98)
//#define SKIP_OR_NOT 1
#define SKIP_OR_NOT (dest != NONS)
#define M(W40, W45, W201) ((((W40) - 0x80) << 10) | (((W45) - (W40)) << 5) | ((W201) - 0x80))
unsigned int utf8_2_win1251(const char *utf8, char *win)
{
    unsigned int dest, p, l1, l2, l3, inc, i, j, b1, b2, b3;
    const unsigned short AR[16] = { M(NONS,NONS,0x86),M(0xA8,0xB8,0x87),M(0x80,0x90,0x95),M(0x81,0x83,0x96),
                                    M(0xAA,0xBA,0x97),M(0xBD,0xBE,NONS),M(0xB2,0xB3,NONS),M(0xAF,0xBF,NONS),
                                    M(0xA3,0xBC,0x91),M(0x8A,0x9A,0x92),M(0x8C,0x9C,0x82),M(0x8E,0x9E,NONS),
                                    M(0x8D,0x9D,0x93),M(NONS,NONS,0x94),M(0xA1,0xA2,0x84),M(0x8F,0x9F,NONS) };
    for (i = 0, j = 0; utf8[i] != '\0'; i += inc)
    {
        b1 = utf8[i]; b2 = utf8[i + 1]; b3 = utf8[i + 2];
        /* Utf8 переводим в Unicode. */
        inc = (0xE5000000u >> (((b1) >> 4) << 1)) & 0x3;
        p = ((((b1) << 12) + (((b2) & 0x3F) << 6) + ((b3) & 0x3F)) & (0x7FFFF >> inc)) >> (((0xC5FFAAAAu >> (((b1) >> 4) << 1)) & 0x3) * 6);
        /* Добавляем все остающиеся на месте. */
        dest = (((inc != 0) & (((p >> 5) != 0x5) | (0xF71C852E >> b2))) - 1) & p; inc++;
        /* Добавляем русские буквы кроме ё и Ё.*/
        dest += ((((p - 0x10) >> 6) != 0x10) - 1) & (p - 0x350);
        /* Добавляем символы из диапазонов: 0x401-0x40F, 0x451-0x45F, 0x2013-0x2022. */
        l1 = ((p >> 4) != 0x40) - 1; l2 = ((p >> 4) != 0x45) - 1; l3 = (((p - 3) >> 4) != 0x201) - 1;
        dest += ((((l2 & (AR[p & 0xF] >> 5)) | (l3 & AR[p & 0xF])) & 0x1F) + ((l1 | l2) & (AR[p & 0xF] >> 10))) + ((l1 | l2 | l3) & 0x80);
        /* Добавляем оставшиеся. */
        dest += (((p !=  0x490) - 1) & 0xA5) | (((p !=  0x491) - 1) & 0xB4) | (((p != 0x2026) - 1) & 0x85) |
                (((p != 0x2030) - 1) & 0x89) | (((p != 0x2039) - 1) & 0x8B) | (((p != 0x203A) - 1) & 0x9B) |
                (((p != 0x20AC) - 1) & 0x88) | (((p != 0x2116) - 1) & 0xB9) | (((p != 0x2122) - 1) & 0x99);
        /* Отличаем настоящий 0 от просто отсутствующих в win 1251 символов. */
        dest += (((b1 == 0) | (dest != 0)) - 1) & NONS;
        win[j] = dest;
        j += SKIP_OR_NOT;
    }
    win[j] = '\0';
    return j;
}
#undef M
#undef NONS
#undef SKIP_OR_NOT

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM