不使用wstring_convert实现string与u16string互转方案
解决C++17中std::string与std::u16string/std::wstring的互转问题(无wstring_convert)
Windows平台:使用系统原生API
你之前尝试MultiByteToWideChar失败,大概率是参数配置或缓冲区处理有误,以下是正确的UTF-8与UTF-16(对应std::u16string/std::wstring)互转实现:
UTF-8转std::u16string
#include <windows.h> #include <string> std::u16string utf8_to_u16(const char* utf8_str) { if (!utf8_str) return {}; // 获取所需缓冲区大小(包含终止符) int buf_len = MultiByteToWideChar(CP_UTF8, 0, utf8_str, -1, nullptr, 0); if (buf_len <= 0) return {}; // 分配wstring缓冲区(Windows下wchar_t为16位,与char16_t兼容) std::wstring temp_buf(buf_len, L'\0'); MultiByteToWideChar(CP_UTF8, 0, utf8_str, -1, temp_buf.data(), buf_len); // 转换为u16string,剔除末尾的终止符 return std::u16string(reinterpret_cast<const char16_t*>(temp_buf.c_str()), buf_len - 1); }
std::u16string转UTF-8
std::string u16_to_utf8(const char16_t* u16_str) { if (!u16_str) return {}; // 获取所需缓冲区大小(包含终止符) int buf_len = WideCharToMultiByte(CP_UTF8, 0, reinterpret_cast<const wchar_t*>(u16_str), -1, nullptr, 0, nullptr, nullptr); if (buf_len <= 0) return {}; std::string utf8_buf(buf_len, '\0'); WideCharToMultiByte(CP_UTF8, 0, reinterpret_cast<const wchar_t*>(u16_str), -1, utf8_buf.data(), buf_len, nullptr, nullptr); // 剔除末尾的终止符 return utf8_buf.substr(0, buf_len - 1); }
std::wstring与std::u16string互转(Windows专属)
Windows下std::wstring本质是UTF-16编码,可直接通过类型转换实现互转:
// wstring转u16string std::u16string wstring_to_u16(const std::wstring& ws) { return std::u16string(reinterpret_cast<const char16_t*>(ws.c_str()), ws.size()); } // u16string转wstring std::wstring u16_to_wstring(const std::u16string& u16s) { return std::wstring(reinterpret_cast<const wchar_t*>(u16s.c_str()), u16s.size()); }
跨平台方案:纯标准C++实现转换
如果你的模块需要跨Windows/Linux/macOS运行,可使用纯标准C++实现UTF-8与UTF-16的互转,无需依赖任何系统API或第三方库:
UTF-8转std::u16string
#include <string> #include <cstdint> std::u16string utf8_to_u16(const char* utf8_str) { std::u16string result; const uint8_t* ptr = reinterpret_cast<const uint8_t*>(utf8_str); while (*ptr) { uint32_t codepoint = 0; // 解析UTF-8字节序列 if ((*ptr & 0x80) == 0) { codepoint = *ptr++; } else if ((*ptr & 0xE0) == 0xC0) { codepoint = (*ptr++ & 0x1F) << 6; codepoint |= (*ptr++ & 0x3F); } else if ((*ptr & 0xF0) == 0xE0) { codepoint = (*ptr++ & 0x0F) << 12; codepoint |= (*ptr++ & 0x3F) << 6; codepoint |= (*ptr++ & 0x3F); } else if ((*ptr & 0xF8) == 0xF0) { codepoint = (*ptr++ & 0x07) << 18; codepoint |= (*ptr++ & 0x3F) << 12; codepoint |= (*ptr++ & 0x3F) << 6; codepoint |= (*ptr++ & 0x3F); } else { // 无效UTF-8序列,跳过当前字节 ++ptr; continue; } // 处理UTF-16代理对(针对U+10000及以上的码点) if (codepoint <= 0xFFFF) { result.push_back(static_cast<char16_t>(codepoint)); } else { codepoint -= 0x10000; result.push_back(static_cast<char16_t>((codepoint >> 10) + 0xD800)); result.push_back(static_cast<char16_t>((codepoint & 0x3FF) + 0xDC00)); } } return result; }
std::u16string转UTF-8
std::string u16_to_utf8(const char16_t* u16_str) { std::string result; const char16_t* ptr = u16_str; while (*ptr) { uint32_t codepoint = 0; // 解析UTF-16代理对 if ((*ptr & 0xFC00) == 0xD800) { if (!*(ptr + 1)) break; // 不完整代理对,终止转换 codepoint = ((static_cast<uint32_t>(*ptr++) & 0x3FF) << 10) | (static_cast<uint32_t>(*ptr++) & 0x3FF); codepoint += 0x10000; } else { codepoint = *ptr++; } // 编码为UTF-8字节序列 if (codepoint <= 0x7F) { result.push_back(static_cast<char>(codepoint)); } else if (codepoint <= 0x7FF) { result.push_back(static_cast<char>((codepoint >> 6) | 0xC0)); result.push_back(static_cast<char>((codepoint & 0x3F) | 0x80)); } else if (codepoint <= 0xFFFF) { result.push_back(static_cast<char>((codepoint >> 12) | 0xE0)); result.push_back(static_cast<char>(((codepoint >> 6) & 0x3F) | 0x80)); result.push_back(static_cast<char>((codepoint & 0x3F) | 0x80)); } else if (codepoint <= 0x10FFFF) { result.push_back(static_cast<char>((codepoint >> 18) | 0xF0)); result.push_back(static_cast<char>(((codepoint >> 12) & 0x3F) | 0x80)); result.push_back(static_cast<char>(((codepoint >> 6) & 0x3F) | 0x80)); result.push_back(static_cast<char>((codepoint & 0x3F) | 0x80)); } } return result; }
以上两种方案都完全避开了已废弃的wstring_convert,可根据你的平台需求选择使用。
内容的提问来源于stack exchange,提问作者Markstar
相关产品推荐
相关产品推荐

