C-如何将宽字符日语字符转换为UTF-8?

时间:2019-10-04 22:31:44

标签: c json encoding utf-8 cjson

尝试将宽字符中存储的日语字符转换为UTF-8,以便使用cJSON库将值存储在json文件中。首先尝试使用wcstombs_s,但显然这不支持日语字符:

size_t len = wcslen(japanese[i].name) + 1;
char* japanese_char = malloc(len);
if (japanese_char == NULL) {
    exit(EXIT_FAILURE);
}
size_t sz;
wcstombs_s(&sz, japanese_char, len, japanese[i].name, _TRUNCATE);

然后,基于其他答案,并且还成功地从json UTF-8转换为wide char,尝试了如下相反的功能,但是目标缓冲区dest仅包含垃圾字符:

size_t wcsChars = wcslen(japanese[i].name);
size_t sizeRequired = WideCharToMultiByte(CP_UTF8, 0, japanese[i].name, wcsChars, NULL, 0, NULL, NULL);
char* dest = calloc(sizeRequired, 1);
WideCharToMultiByte(CP_UTF8, 0, japanese[i].name, wcsChars, dest, sizeRequired, NULL, NULL);
free(dest);

我要转换的宽字符(wchar_t)是ササササササササササササササササ存储在japanese[i].name(结构中的wchar_t*)中。目的是使用cJSON的cJSON_CreateString将值保存在UTF-8编码的json文件中。

问题:将日语从wchar_t转换为C语言(非C ++)中的UTF-8字符的正确方法是什么?

1 个答案:

答案 0 :(得分:0)

您的wcstombs_s()代码正在将错误的值传递给sizeInBytes参数:

  

sizeInBytes

     

mbstr 缓冲区的大小(以字节为单位)。

您传递的是japanese[i].name字符计数,而不是japanese_char的分配的 byte 计数。它们的值不相同。

Unicode代码点分别使用2或4个字节以UTF-16编码(wchar_t字符串在Windows上进行编码),而在UTF-8中则根据其值分别使用1-4个字节编码。 U+0080..U+FFFF范围内的Unicode代码点在UTF-8中比在UTF-16中占用更多的字节,因此您的japanese_char缓冲区实际需要分配的空间可能大于{{1} }数据。就像可以调用japanese[i].name以确定所需的目标缓冲区大小一样,您可以使用WideCharToMultiByte()做同样的事情。

wcstombs_s()

由于您将显式大小传递给size_t len = 0; wcstombs_s(&len, NULL, 0, japanese[i].name, _TRUNCATE); if (len == 0) exit(EXIT_FAILURE); char* japanese_char = malloc(len); if (!japanese_char) exit(EXIT_FAILURE); wcstombs_s(&len, japanese_char, len, japanese[i].name, _TRUNCATE); ... free(japanese_char); 参数,因此您的WideCharToMultiByte()代码不是以空终止的dest

  

cchWideChar

     

lpWideCharStr指示的字符串的大小(以字符为单位)。或者,如果字符串以空值结尾,则可以将此参数设置为-1。如果将cchWideChar设置为0,则函数将失败。

     

如果此参数为-1,则该函数处理整个输入字符串,包括终止的空字符。因此,结果字符串具有一个终止的空字符,并且该函数返回的长度包括该字符。

     

如果将此参数设置为正整数,则该函数将精确处理指定数量的字符。如果提供的大小不包含终止的空字符,则结果字符串不是以终止的字符串,并且返回的长度不包含此字符。

cchWideChar期望以空值结尾的cJSON_CreateString()字符串。因此,您需要:

  • 将+1添加到char*的{​​{1}}参数中,以说明缺少的空终止符。
num
  • 将+1添加到calloc()的返回值中,或将size_t wcsChars = wcslen(japanese[i].name); size_t len = WideCharToMultiByte(CP_UTF8, 0, japanese[i].name, wcsChars, NULL, 0, NULL, NULL); char* japanese_char = malloc(len + 1); if (!japanese_char) exit(EXIT_FAILURE); WideCharToMultiByte(CP_UTF8, 0, japanese[i].name, wcsChars, japanese_char, len, NULL, NULL); japanese_char[len] = '\0'; ... free(japanese_char); 的{​​{1}}参数设置为-1,以在输出中包括空终止符。
wcslen()
cchWideChar