首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何将宽字符日语字符转换为UTF-8?

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

Stack Overflow用户
提问于 2019-10-04 22:31:44
回答 1查看 1K关注 0票数 0

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

代码语言:javascript
复制
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 8到wide的成功转换中,尝试了如下相反的函数,但是目标缓冲区dest只包含垃圾字符:

代码语言:javascript
复制
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文件中。

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

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-10-04 23:00:29

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

sizeInBytes

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

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

Unicode编码点使用UTF-16 ( wchar_t字符串在Windows上的编码方式)每个使用2或4个字节编码,在UTF-8中每个编码使用1-4字节,这取决于它们的值。U+0080..U+FFFF范围内的Unicode代码点在UTF-8中所占的字节比UTF-16所占的字节要多,因此可能需要实际分配比japanese[i].name数据更大的japanese_char缓冲区。就像您可以调用WideCharToMultiByte()来确定所需的目标缓冲区大小一样,您也可以对wcstombs_s()做同样的事情。

代码语言:javascript
复制
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,则函数将处理整个输入字符串,包括终止空字符。因此,得到的字符串具有一个终止空字符,函数返回的长度包含这个字符。

如果此参数设置为正整数,则该函数将处理指定数目的字符。如果所提供的大小不包括终止空字符,则得到的字符串不为空终止,返回的长度不包括此字符。。

cJSON_CreateString()需要一个以空结尾的char*字符串。所以你需要:

  • 将+1添加到calloc()num参数中,以解释缺少的空终止符.

代码语言:javascript
复制
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添加到wcslen()的返回值,或将WideCharToMultiByte()cchWideChar参数设置为-1,以便在输出中包含空终止符。

代码语言:javascript
复制
size_t wcsChars = wcslen(japanese[i].name) + 1;
size_t len = WideCharToMultiByte(CP_UTF8, 0, japanese[i].name, wcsChars, NULL, 0, NULL, NULL);
if (len == 0)
    exit(EXIT_FAILURE);
char* japanese_char = malloc(len);
if (!japanese_char)
    exit(EXIT_FAILURE);
WideCharToMultiByte(CP_UTF8, 0, japanese[i].name, wcsChars, japanese_char, len, NULL, NULL);
...
free(japanese_char);
代码语言:javascript
复制
size_t len = WideCharToMultiByte(CP_UTF8, 0, japanese[i].name, -1, NULL, 0, NULL, NULL);
if (len == 0)
    exit(EXIT_FAILURE);
char* japanese_char = malloc(len);
if (!japanese)
    exit(EXIT_FAILURE);
WideCharToMultiByte(CP_UTF8, 0, japanese[i].name, -1, japanese_char, len, NULL, NULL);
...
free(dest);
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58243806

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档