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

标签 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 到宽字符的成功转换中,尝试了相反的函数,如下所示,但目标缓冲区 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/

相关文章:

javascript - 将json发送的两个数组分开

java.lang.RuntimeException : Unable to invoke no-args constructor for class DBExecuter. Queryjson$valIOConfigclass

perl - 为什么 PerlIO::encoding 插入额外的 utf8 层?

c - 如何将 Unicode 转义字符转换为 utf8?

c - 我正在丢失内存分配吗?

c - 如何将数组添加到位域结构?

c - 为什么在下一个代码中 c = 1?

python - 类型错误:字符串索引必须是整数(使用 pandas Dataframe)

jquery - 为什么 IE 在仅使用阿拉伯语或波斯语等其他语言发送 ajax 请求时无法识别字符

c - GNU ld 是否可以选择完全省略 -dynamic-linker (PT_INTERP)?