尝试将存储在宽字符中的日语字符转换为 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 到宽字符的成功转换中,尝试了相反的函数,如下所示,但目标缓冲区 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
中的ササササササササササササササササ
(a结构中的 wchar_t*
)。目的是使用cJSON的cJSON_CreateString
将值保存在UTF-8编码的json文件中。
问题:在 C(而不是 C++)中将日语从 wchar_t 转换为 UTF-8 字符的正确方法是什么?
最佳答案
您的 wcstombs_s()
代码将错误的值传递给 sizeInBytes
参数:
sizeInBytes
The size in bytes of the
mbstr
buffer.
您传递的是 japanese[i].name
的字符计数,而不是 japanese_char< 分配的字节计数
。它们不是相同的值。
Unicode 代码点在 UTF-16 中使用 2 或 4 个字节进行编码(wchar_t
字符串在 Windows 上的编码方式),每个使用 2 或 4 个字节,在 UTF-8 中使用 1-4 个字节进行编码,具体取决于它们的值值(value)。 U+0080..U+FFFF
范围内的 Unicode 代码点在 UTF-8 中比在 UTF-16 中占用更多字节,因此您的 japanese_char
实际上需要分配的缓冲区大于您的 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);
<小时/>
由于您向 cchWideChar
参数传递了显式大小,因此您的 WideCharToMultiByte()
代码不是以 null 终止的 dest
。
cchWideChar
Size, in characters, of the string indicated by lpWideCharStr. Alternatively, this parameter can be set to -1 if the string is null-terminated. If cchWideChar is set to 0, the function fails.
If this parameter is -1, the function processes the entire input string, including the terminating null character. Therefore, the resulting character string has a terminating null character, and the length returned by the function includes this character.
If this parameter is set to a positive integer, the function processes exactly the specified number of characters. If the provided size does not include a terminating null character, the resulting character string is not null-terminated, and the returned length does not include this character.
cJSON_CreateString()
需要一个以 null 结尾的 char*
字符串。所以你需要:
- 向
calloc()
的num
参数添加 +1 以解决缺少空终止符的问题。
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);
- 在
wcslen()
的返回值上加+1,或者将WideCharToMultiByte()
的cchWideChar
参数设置为-1,以在输出中包含空终止符。
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);
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);
关于C - 如何将宽字符日语字符转换为 UTF-8?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58243806/