Как конвертировать (char *) из ISO-8859-1 в UTF-8 в C ++ мультиплатформенно? - PullRequest
4 голосов
/ 07 апреля 2011

Я меняю программное обеспечение на C ++, которое обрабатывает тексты в формате ISO Latin 1 для хранения данных в базе данных на SQLite.
Проблема в том, что SQLite работает в UTF-8 ... и модулях Javaкоторые используют ту же работу с базой данных в UTF-8.

Я хотел иметь способ преобразования символов ISO Latin 1 в символы UTF-8 перед сохранением в базе данных.Мне нужно, чтобы он работал в Windows и Mac.

Я слышал, что ICU сделает это, но я думаю, что он слишком раздутый.Мне просто нужна простая система преобразования (желательно туда-сюда) для этих двух кодировок.

Как бы я это сделал?

Ответы [ 4 ]

15 голосов
/ 07 апреля 2011

ISO-8859-1 был включен в качестве первых 256 кодовых точек ISO / IEC 10646 и Unicode. Таким образом, преобразование довольно просто.

для каждого символа:

uint8_t ch = code_point; /* assume that code points above 0xff are impossible since latin-1 is 8-bit */

if(ch < 0x80) {
    append(ch);
} else {
    append(0xc0 | (ch & 0xc0) >> 6); /* first byte, simplified since our range is only 8-bits */
    append(0x80 | (ch & 0x3f));
}

Подробнее см. http://en.wikipedia.org/wiki/UTF-8#Description.

РЕДАКТИРОВАТЬ: в соответствии с комментарием ninjalj , latin-1 преобразует direclty в первые 256 кодовых точек Unicode, поэтому приведенный выше алгоритм должен работать.

1 голос
/ 06 октября 2016

TO C ++ Я использую это:

std::string iso_8859_1_to_utf8(std::string &str)
{
    string strOut;
    for (std::string::iterator it = str.begin(); it != str.end(); ++it)
    {
        uint8_t ch = *it;
        if (ch < 0x80) {
            strOut.push_back(ch);
        }
        else {
            strOut.push_back(0xc0 | ch >> 6);
            strOut.push_back(0x80 | (ch & 0x3f));
        }
    }
    return strOut;
}
1 голос
/ 07 апреля 2011

Если рамки кодировки общего назначения (например, iconv) слишком раздуты для вас, накатайте свою собственную.

Составьте статическую таблицу перевода (последовательность char в последовательность UTF-8), соберите свой собственный перевод.В зависимости от того, что вы используете для хранения строк (буферы символов или std :: string или что), это будет выглядеть несколько иначе, но идея в том, чтобы прокрутить исходную строку, заменить каждый символ кодом более 127 с его UTF-8ответная строка.Поскольку это может потенциально увеличить длину строки, делать это на месте было бы довольно неудобно.Для получения дополнительной выгоды вы можете сделать это в два прохода: проход один определяет необходимый размер строки назначения, проход второй выполняет перевод.

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

Если вы не возражаете против создания дополнительной копии, вы можете просто «расширить» свои символы ISO Latin 1 до 16-битных символов и таким образом получить UTF-16.Тогда вы можете использовать что-то вроде UTF8-CPP для преобразования его в UTF-8.

На самом деле, я думаю, что UTF8-CPP может даже напрямую конвертировать ISO Latin 1 в UTF-8 (utf16to8функция), но вы можете получить предупреждение.

Конечно, это должна быть настоящая ISO Latin 1, а не Windows CP 1232.

...