尝试将宽字符中存储的日语字符转换为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字符的正确方法是什么?
答案 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()
字符串。因此,您需要:
char*
的{{1}}参数中,以说明缺少的空终止符。num
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