将String转换为UTF8字符串所必需的

时间:2015-06-18 14:42:35

标签: c++ c utf-8 iconv wchar-t

问题陈述: 我需要将生成的字符串转换为UTF8字符串,这个生成的字符串扩展了ascii字符,我在Linux系统上(2.6.32-358.el6.x86_64)。

  

POC仍在进行中,所以我只能提供小代码样本   完整的解决方案只能在准备好后发布。

为什么我需要UFT8(我已将扩展的ascii字符存储在必须为UTF8的字符串中)。

我如何处理:

  • 将生成的字符串转换为wchar_t字符串。

请查看以下示例代码

int main(){
  char  CharString[] = "Prova";
  iconv_t cd;
  wchar_t  WcharString[255];

  size_t size= mbstowcs(WcharString, CharString, strlen(CharString));

  wprintf(L"%ls\n", WcharString);

  wprintf(L"%s\n", WcharString);

  printf("\n%zu\n",size);
}

这里有一个问题:

输出

  

PROVA ?????

     

取值

  1. 为什么这里不打印尺寸?
  2. 为什么第二个printf只打印一个字符。
  3. 如果我在两个打印的字符串之前打印尺寸,则只打印5并且控制台中缺少两个字符串。
  4. <小时/> 转到第二部分:

    现在我将有一个wchar_t字符串,我想将其转换为UTF8字符串

    为此,我正在浏览并发现iconv将在这里提供帮助。

    问题在这里 这些是我在manual

    中找到的方法
    **iconv_t iconv_open(const char *, const char *);
    
    size_t  iconv(iconv_t, char **, size_t *, char **, size_t *);
    
    int     iconv_close(iconv_t);**
    

    在进入iconv之前,我是否需要将wchar_t数组转换回char数组?

    请就上述问题提供建议。

    扩展ascii我正在谈论请在下面标记的快照中看到字母i enter image description here

2 个答案:

答案 0 :(得分:4)

对于你的第一个问题(我将其解释为&#34;为什么所有的输出都不是我所期望的&#34;):

  1. &#39; ?????&#39;来自?在调用mbstowcs(WcharString, CharString, strlen(CharString))中,最后一个参数(strlen(CharString))是输出缓冲区的长度,而不是输入字符串的长度。 mbstowcs写入的宽字符数不会超过,包括NUL终结符。由于转换需要6个宽字符,包括终结符,并且您只允许它写入5个宽字符,因此生成的宽字符串不会终止NUL,并且当您尝试将其打印出来时,最终会在结束后打印垃圾。转换后的字符串。因此?????。您应该使用wchar_t中的输出缓冲区的大小(在本例中为255)。

  2. 为什么第二个wprintf只打印一个字符?当您使用宽字符串参数调用wprintf时,必须使用{{1}格式代码(或者更确切地说,%ls转换需要使用%s长度修饰符进行限定)。如果您使用l而不使用%s,则l会将字符串解释为wprintf,并且会在输出时将每个字符转换为char*它。但是,由于参数实际上是一个宽字符串,因此字符串中的第一个wchar_twchar_t,这是某个整数大小的数字L"p"。这意味着0x70的第二个字节(从结尾算起,因为你有一个小端架构)是0,所以如果你将字符串视为字符的字符串 ,它将在wchar_t之后立即终止。所以只打印一个字符。

  3. 为什么最后一次p打印没有?在C中,输出流可以是宽流或者字节流,但是在打开流时没有指定。 (并且,无论如何,标准输出已经为您打开。)这称为流的方向。新打开的流是未定向的,当您第一次输出到流时,方向是固定的。如果第一个输出呼叫是广泛呼叫,如printf,则流是一个宽流;否则,它是一个字节流。设置后,方向是固定的,您不能使用错误方向的输出调用。因此wprintf是非法的,除了引发错误之外什么都不做。

  4. 现在,让我们继续讨论第二个问题:我该怎么办?

    首先,您需要清楚输入的格式以及输出方式。在Linux上,您根本不可能想要使用printf。输入字符串最可能的情况是它已经是UTF-8,或者它是某些ISO-8859-x编码。输出的最可能情况是相同的:要么是UTF-8,要么是一些ISO-8859-x编码。

    不幸的是,您的程序无法知道控制台所期望的编码。输出甚至可能不会进入控制台。同样,您的程序实际上无法知道输入字符串中使用了哪种ISO-8859-x编码。 (如果它是字符串文字,则在调用编译器时可能会指定编码,但没有提供信息的标准方法。)

    如果由于非ascii字符未正确显示而无法查看输出,则应首先确保控制台配置为使用与程序输出相同的编码。如果程序将UTF-8发送到显示ISO-8859-15的控制台,则文本将无法正常显示。理论上,您的语言环境设置包括控制台使用的编码,但如果您使用的是远程控制台(例如,通过Windows计算机中的PuTTY),则控制台不是Linux环境的一部分,并且默认语言环境可能不正确。最简单的解决方法是正确配置控制台,但也可以更改Linux区域设置。

    您从字节字符串中使用wchar_t这一事实表明您认为原始字符串是UTF-8。所以问题似乎不太可能是你需要将它转换为 UTF-8。

    您当然可以使用mbstowcs将字符串从一种编码转换为另一种编码;你不需要经过iconv这样做。但您确实需要知道实际的输入编码和所需的输出编码。

答案 1 :(得分:1)

对utf8使用iconv不是一个好主意。只需自己实现utf8的定义。从描述https://en.wikipedia.org/wiki/UTF-8中可以很容易地在C中完成。 你甚至不需要wchar_t,只需使用uint32_t作为你的角色。 如果你自己实现,你将学到很多东西,你的程序将因不使用mb或iconv函数而获得速度。