将C语言中的`char *`转换为UTF-8,或者使用xmlwriter时?

时间:2019-07-10 16:42:56

标签: c utf-8 libxml2

我正在使用libxml/xmlwriter在程序中生成XML文件。

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

通常,我对s的内容没有太多控制权,因此我不能保证它会以UTF-8格式正确。通常是这样,但是如果不是这样,则生成的XML格式会错误。

我想找到的是一种将s转换为有效UTF-8的方法,其中s中的任何无效字符序列都被转义符或删除了。

或者,如果有xmlTextWriterWriteAttribute的替代方法,或者在初始化XML编写器时可以传递一些选项,以确保它始终写入有效的UTF-8,那会更好。

还有一件事要提到的是,该解决方案必须在Linux和OSX上都可以使用。理想情况下,编写尽可能少的我自己的代码! :P

3 个答案:

答案 0 :(得分:0)

如果字符串以ASCII编码,则它将始终是有效的UTF-8字符串。 这是因为UTF-8向后兼容ASCII编码。

请参阅Wikipedia here的第二段。

Windows主要与UTF-16配合使用,这意味着您必须先将UTF-16转换为UTF-8,然后再将字符串传递给XML库。

答案 1 :(得分:0)

如果您有8位ASCII输入,那么您就可以简单地将任何字符代码> 127垃圾掉。

如果您有一些晦涩的UTF-8,则很容易解析,但是生成的widechar符号编号可能不在unicode范围内。您可以使用mbrlen()来分别验证每个字符。

我正在使用未签名的字符来描述它。如果必须使用带符号的字符,则> 128表示<0。

最简单的方法:

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代码。 / p>

答案 2 :(得分:0)

char是一个单字节字符,而UTF码点的范围从00x10FFFFF,那么如何只用一个字节表示一个UTF字符呢?

首先,您需要一个wchar_t字符。它们与常规wprintf(3)例程的printf(3)版一起使用。如果您对此有所了解,您会发现根据您的UTF-8设置,将UTF代码点映射到有效的setlocale(3)编码是很明智的。查看参考的那些手册页,您将了解所面临的任务。

C标准完全支持宽字符集...但是您必须通过国际化库和可用的语言环境来使用它。