void utf8_to_gbk(const char *utf8_str, char *gbk_str, size_t gbk_buf_size) {
// 1. 参数验证
if (utf8_str == NULL || gbk_str == NULL || gbk_buf_size == 0) {
if (gbk_str && gbk_buf_size > 0) gbk_str[0] = '\0';
return;
}
// 2. 空字符串处理
if (utf8_str[0] == '\0') {
gbk_str[0] = '\0';
return;
}
// 3. 检查UTF-8有效性(ESP32的iconv对无效序列很敏感)
if (!is_valid_utf8(utf8_str)) {
ESP_LOGE(TAG, "无效的UTF-8序列");
strncpy(gbk_str, utf8_str, gbk_buf_size - 1);
gbk_str[gbk_buf_size - 1] = '\0';
return;
}
// 4. 尝试多种编码组合(ESP32的iconv实现可能有差异)
iconv_t cd = (iconv_t)-1;
const char *encodings[] = {
"GBK//IGNORE", "UTF-8", // 首选:忽略无法转换的字符
"CP936//IGNORE", "UTF-8", // 备选:Windows代码页
"GBK", "UTF-8", // 再次尝试
"CP936", "UTF-8"
};
for (int i = 0; i < sizeof(encodings) / sizeof(encodings[0]); i += 2) {
cd = iconv_open(encodings, encodings[i + 1]);
if (cd != (iconv_t)-1) {
ESP_LOGI(TAG, "使用编码: %s -> %s", encodings[i + 1], encodings);
break;
}
}
if (cd == (iconv_t)-1)
{
ESP_LOGE(TAG, "所有编码组合都失败");
strncpy(gbk_str, utf8_str, gbk_buf_size - 1);
gbk_str[gbk_buf_size - 1] = '\0';
return;
}
/*
// 创建转换器
iconv_t cd = iconv_open("GBK//IGNORE", "UTF-8"); //创建从 UTF-8 到 GBK 的编码转换器 iconv_t 是转换会话的句柄(类似文件句柄) 如果失败返回 (iconv_t)-1
if (cd == (iconv_t)-1) {//说明转换失败
ESP_LOGE(TAG, " 转换失败");
strncpy(gbk_str, utf8_str, gbk_buf_size-1);//直接复制原始字符串(避免程序完全失败)
gbk_str[gbk_buf_size - 1] = '\0'; // 确保终止
return;
}*/
// 设置转换参数
size_t in_len = strlen(utf8_str); // 输入字符串长度
size_t out_len = gbk_buf_size - 1; // 输出缓冲区大小(预留1字节给终止符)
char *in_buf = (char *)utf8_str; // 输入缓冲区指针(需要非const)
char *out_buf = gbk_str; // 输出缓冲区指针
// 保存原始指针用于错误处理
char *original_out_buf = gbk_str;
// 6. 执行转换
if (iconv(cd, &in_buf, &in_len, &out_buf, &out_len) == (size_t)-1) {
// 详细的错误信息
int err = errno;
const char *error_msg = "";
switch (err) {
case EILSEQ: error_msg = "无效的多字节序列"; break;
case EINVAL: error_msg = "不完整的多字节序列"; break;
case E2BIG: error_msg = "输出缓冲区不足"; break;
default: error_msg = "未知错误LIN188"; break;
}
ESP_LOGE(TAG, "转换失败: %s (errno: %d)", error_msg, err);
// 转换失败时回退
strncpy(original_out_buf, utf8_str, gbk_buf_size - 1);
original_out_buf[gbk_buf_size - 1] = '\0';
} else {
// 确保字符串终止
*out_buf = '\0'; // 确保字符串终止 out_buf 指针已经被 iconv 更新到最后一个写入位置的后面的地址 在字符串末尾添加终止符。 只在当前指针位置写入一个终止符
ESP_LOGI(TAG, "转换成功,剩余输入: %d字节, 剩余输出: %d字节",
in_len, out_len);
}
iconv_close(cd); //关闭转换器
}
使用iconv进行编码转换,转换失败是什么问题?
-
wangjieaaa
- Posts: 1
- Joined: Tue Sep 02, 2025 3:12 am
使用iconv进行编码转换,转换失败是什么问题?
- Attachments
-
- 微信图片_20250902105004_394_46.png (44.14 KiB) Viewed 2438 times
-
- wechat_2025-09-02_111719_721.png (98.37 KiB) Viewed 2438 times
Who is online
Users browsing this forum: No registered users and 3 guests