将std::string编码/解码为UTF-16

12

我需要处理一种文件格式(需要读取和写入),其中字符串以UTF-16(每个字符2个字节)编码。由于在应用程序领域中很少使用ASCII表之外的字符,因此我的C++模型类中的所有字符串都存储在std::string实例中(以UTF-8编码)。

我正在寻找一个库(在STL和Boost中搜索没有结果)或一组C/C++函数来处理这个std::string <-> UTF-16转换,包括从文件格式(实际上是按字节流建模)加载或保存,同时生成/识别代理对和其他Unicode相关的操作(我承认自己不是专家)...

有什么建议吗?谢谢!

编辑:忘记提到它应该是跨平台的(Win/Mac),并且不能使用C++11。


啊,我研究了一下ICU,但它对于我的任务来说似乎太庞大了。 - Peter
如果你只针对Windows平台,使用WideCharToMultiByte函数;在其他情况下,请使用ICU。虽然可以自己实现,但最好不要这样做。 - Mooing Duck
这个问题已经被问了很多次,我最熟悉的是 https://dev59.com/TXVC5IYBdhLWcg3w51ry - Mark Ransom
哦,嘿,Boost有Unicode迭代器! - Mooing Duck
3个回答

19

C++11具备此功能:

std::string s = u8"Hello, World!";

// #include <codecvt>
std::wstring_convert<std::codecvt<char16_t,char,std::mbstate_t>,char16_t> convert;

std::u16string u16 = convert.from_bytes(s);
std::string u8 = convert.to_bytes(u16);

据我所知,目前唯一实现这一功能的是libc++。C++11还有std::codecvt_utf8_utf16<char16_t>,其他一些实现也有此功能。具体来说,在VS 2010及以上版本中可以使用codecvt_utf8_utf16,因为Windows使用wchar_t表示UTF-16,所以您可以使用它来在UTF-8和Windows本地编码之间进行转换。(参见此处)


特化版codecvt<char16_t,char,mbstate_t>将UTF-16和UTF-8编码方案相互转换,特化版codecvt<char32_t,char,mbstate_t>将UTF-32和UTF-8编码方案相互转换。

— [locale.codecvt] 22.4.1.4/3


哦,而且std::codecvt特化版有受保护的析构函数,wstring_convert需要访问析构函数,因此您确实需要一个适配器:

template <class Facet>
class usable_facet : public Facet {
public:
    using Facet::Facet; // inherit constructors
    ~usable_facet() {}

    // workaround for compilers without inheriting constructors:
    // template <class ...Args> usable_facet(Args&& ...args) : Facet(std::forward<Args>(args)...) {}
};

template<typename internT, typename externT, typename stateT> 
using codecvt = usable_facet<std::codecvt<internT, externT, stateT>>;

std::wstring_convert<codecvt<char16_t,char,std::mbstate_t>> convert;

1
哇,什么?!+1 我从来没见过这个 :) - Felix Dombek
嗯,我制作了一个测试用例来测试扩展平面字符,但是IDEOne无法编译它:http://ideone.com/UdZcL - Mooing Duck
@MooingDuck 不幸的是,即使在gcc 4.7中,libstdc++仍然没有实现这些特化。 - bames53
你如何管理utf-16 BE或utf-16 LE,并能在它们之间切换(在写入文件时)? - Sandburg
1
@Sandburg UTF编解码器的模板参数之一是codecvt_mode,它允许您指定选项,如字节序和BOM。https://en.cppreference.com/w/cpp/locale/codecvt_mode - bames53

3

你看过Boost.Locale了吗?这个页面特别介绍了如何进行UTF到UTF的转换以及如何将其与IOStreams集成。


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接