C - 如何将宽字符日文字符转换为 UTF-8?
C - How to convert wide char Japanese characters to UTF-8?
尝试将 wide char 中存储的日语字符转换为 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
中(结构中的 wchar_t*
)。 Objective是使用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 中编码(wchar_t
字符串在 Windows 中编码)每个使用 2 或 4 个字节,在 UTF-8 中每个使用 1-4 个字节,取决于它们的价值。 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()
代码不是空终止 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*
字符串。所以你需要:
- 将 +1 添加到
calloc()
的 num
参数以解决缺少的空终止符。
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] = '[=11=]';
...
free(japanese_char);
- 将+1添加到
wcslen()
的return值,或将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);
尝试将 wide char 中存储的日语字符转换为 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
中(结构中的 wchar_t*
)。 Objective是使用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 中编码(wchar_t
字符串在 Windows 中编码)每个使用 2 或 4 个字节,在 UTF-8 中每个使用 1-4 个字节,取决于它们的价值。 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()
代码不是空终止 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*
字符串。所以你需要:
- 将 +1 添加到
calloc()
的num
参数以解决缺少的空终止符。
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] = '[=11=]';
...
free(japanese_char);
- 将+1添加到
wcslen()
的return值,或将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);