You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C++中将指定编码的字符串转换为UTF-16宽字符串?

解决方案

存在多种工具和方法可以实现已知编码的std::string到UTF-16宽字符串的转换,std::wstring_convert确实无法直接通过编码名称字符串指定转换规则,但可以通过以下几种更实用的途径实现需求:

1. Windows平台:使用系统原生API

Windows系统的MultiByteToWideCharAPI直接支持指定代码页(GB-18030对应的代码页为CP_GB18030),无需依赖第三方库,转换效率和兼容性都有保障:

#include <string>
#include <windows.h>

std::wstring gb18030_to_utf16(const std::string& gb_str) {
    if (gb_str.empty()) return {};

    // 计算所需UTF-16缓冲区大小
    const int wide_buf_size = MultiByteToWideChar(CP_GB18030, 0, gb_str.c_str(), (int)gb_str.size(), nullptr, 0);
    if (wide_buf_size == 0) return {};

    std::wstring utf16_str(wide_buf_size, 0);
    MultiByteToWideChar(CP_GB18030, 0, gb_str.c_str(), (int)gb_str.size(), utf16_str.data(), wide_buf_size);
    return utf16_str;
}

2. 跨平台方案:使用第三方Unicode处理库

标准库对非UTF编码的支持有限,跨平台场景推荐使用成熟的第三方库,它们支持通过编码名称字符串指定转换规则:

ICU库(跨平台首选)

ICU是专业的Unicode处理库,支持几乎所有常见编码,可直接通过编码名(如"GB18030")完成转换:

#include <string>
#include <unicode/ucnv.h>
#include <unicode/ustring.h>

std::wstring convert_to_utf16(const std::string& src_str, const char* src_encoding) {
    UErrorCode status = U_ZERO_ERROR;
    UConverter* converter = ucnv_open(src_encoding, &status);
    if (U_FAILURE(status)) return {};

    // 计算所需UTF-16缓冲区大小
    int32_t dest_len = ucnv_toUChars(converter, nullptr, 0, src_str.c_str(), (int32_t)src_str.size(), &status);
    if (status != U_BUFFER_OVERFLOW_ERROR) {
        ucnv_close(converter);
        return {};
    }
    status = U_ZERO_ERROR;

    std::wstring dest_str(dest_len, 0);
    ucnv_toUChars(converter, reinterpret_cast<UChar*>(dest_str.data()), dest_len, 
                  src_str.c_str(), (int32_t)src_str.size(), &status);
    
    ucnv_close(converter);
    return U_SUCCESS(status) ? dest_str : std::wstring{};
}

// 使用示例:
// std::wstring utf16_str = convert_to_utf16(gb_str, "GB18030");

iconv库(POSIX系统常用)

iconv是POSIX标准的编码转换库,同样支持通过编码名称指定转换规则:

#include <string>
#include <iconv.h>
#include <cstring>

std::wstring convert_to_utf16(const std::string& src_str, const char* src_encoding) {
    // 根据系统字节序选择UTF-16LE或UTF-16BE
    iconv_t converter = iconv_open("UTF-16LE", src_encoding);
    if (converter == (iconv_t)-1) return {};

    char* in_buf = const_cast<char*>(src_str.c_str());
    size_t in_remaining = src_str.size();
    const size_t out_buf_size = in_remaining * 2;
    char* out_buf = new char[out_buf_size];
    char* out_start = out_buf;
    size_t out_remaining = out_buf_size;

    const size_t convert_result = iconv(converter, &in_buf, &in_remaining, &out_buf, &out_remaining);
    const bool success = (convert_result != (size_t)-1) && (in_remaining == 0);

    std::wstring dest_str;
    if (success) {
        const size_t converted_len = out_buf_size - out_remaining;
        dest_str = std::wstring(reinterpret_cast<wchar_t*>(out_start), converted_len / sizeof(wchar_t));
    }

    delete[] out_start;
    iconv_close(converter);
    return dest_str;
}

关于std::wstring_convert的补充说明

标准库的std::wstring_convert需要配合std::codecvt的特化版本使用,但标准库仅提供了UTF相关的特化(如codecvt_utf8_utf16),没有内置GB-18030这类编码的支持。如果一定要基于它实现,需要自行编写对应的codecvt facet,这一过程繁琐且易出错,远不如上述方案高效可靠。此外,C++17开始std::wstring_convert和std::codecvt已被标记为弃用,更不推荐在新项目中使用。

内容的提问来源于stack exchange,提问作者Mikhail Svetlov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 21:35:23