Конвертировать `char *` в UTF-8 в C или при использовании xmlwriter? - PullRequest
0 голосов
/ 10 июля 2019

Я использую libxml/xmlwriter для генерации XML-файла в программе.

const char *s = someCharactersFromSomewhere();
xmlTextWriterWriteAttribute (writer, _xml ("value"), _xml (s));

Как правило, я не контролирую содержимое s, поэтому не могу гарантировать, что оно будет хорошо отформатировано в UTF-8. В основном это так, но если нет, то генерируемый XML будет искажен.

Я хотел бы найти способ конвертировать s в действительный UTF-8 с любыми недопустимыми последовательностями символов в s, замененными на escape-символы или удаляемыми.

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

Еще одна вещь, которую стоит упомянуть, это решение должно работать как с Linux, так и с OSX. В идеале писать как можно меньше своего собственного кода! : P

Ответы [ 3 ]

0 голосов
/ 10 июля 2019

Если у вас есть 8-битный ввод ascii, то вы можете просто выбросить любой код символа> 127.

Если у вас есть какой-то хитрый UTF-8, его довольно легко разобрать, но номер символа в широком символе, который выГенерирование может быть вне диапазона Юникода.Вы можете использовать mbrlen() для индивидуальной проверки каждого символа.

Я описываю это, используя символы без знака.Если вы должны использовать знаковые символы, то> 128 означает <0. </p>

В самом простом виде:

Until the null byte
 1 If the next byte is 0, then end the loop
 2 If the next byte is < 128 then it is ascii, so keep it
 3 If the next byte is >=128 < 128+64 it is invalid - discard it
 4 If the next byte is >= 128+64 then it is probably a proper UTF-8 lead byte
   call size_t mbrlen(const char *s, size_t n, mbstate_t *ps);
   to see how many bytes to keep 
   if mbrlen says the code is bad (either the lead byte or the trail bytes),
     skip 1 byte. Rule 3 will skip the rest.

Еще более простая логика просто несколько раз вызывает mbrlen, поскольку она может принять низкий диапазон ascii.

Вы можете предположить, что вся «мебель» файла (например, xml <> / символы, пробелы, кавычки и символы новой строки) не будут изменены этим редактированием, так как все они действительны для 7-битного asciiкоды.

0 голосов
/ 11 июля 2019

char является однобайтовым символом, в то время как кодовые точки UTF варьируются от 0 до 0x10FFFFF, так как вы представляете символ UTF только в одном байте?

Прежде всего вам нужен wchar_t символ. Они используются с wprintf(3) версиями обычных printf(3) подпрограмм. Если вы немного покопаетесь в этом, вы увидите, что преобразование ваших кодовых точек UTF в правильную кодировку UTF-8 довольно простое, в зависимости от ваших настроек setlocale(3). Посмотрите на те справочные страницы, на которые есть ссылки, и вы получите представление о задаче, с которой вы столкнулись.

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

0 голосов
/ 10 июля 2019

Если строка закодирована в ASCII, то это всегда будет действительная строка UTF-8.Это потому, что UTF-8 обратно совместим с кодировкой ASCII.

См. Второй абзац в Википедии здесь .

Windows в основном работает с UTF-16, это означает, что выперед передачей строки в библиотеку XML потребуется преобразовать UTF-16 в UTF-8.

...