这是一个老答案。
有关最新更新,请参见UTF-8 Everywhere。
意见:是的,应该将UTF-16视为有害的。它存在的根本原因是因为一段时间以前,人们曾经误导了Widechar将成为现在的UCS-4。
尽管UTF-8具有“以语言为中心”的特征,但应将其视为唯一有用的文本编码。可以认为,程序,网页和XML文件,OS文件名以及其他计算机对计算机文本接口的源代码应该永远都不存在。但是当他们这样做时,文本不仅适合人类读者。
另一方面,UTF-8开销是要付出的代价,虽然它具有明显的优势。优点,例如与仅通过传递字符串的无意识代码兼容char*
。这是一件了不起的事。与UTF-8中相比,UTF-16中的SHORTER有用的字符很少。
我相信所有其他编码最终都会消失。这涉及到MS-Windows,Java,ICU,python停止使用它们作为收藏夹。经过长期的研究和讨论,我公司的开发约定禁止在OS API调用之外的任何地方使用UTF-16,尽管这对我们的应用程序中性能的重要性以及我们使用Windows的事实也是如此。开发了转换功能,可以将始终假定的UTF8转换std::string
为Windows本身不正确支持的本机UTF-16 。
对于那些说“ 在需要的地方使用需要的东西 ”的人,我说:在任何地方使用相同的编码有很大的优势,我认为没有足够的理由这样做。特别是,我认为添加wchar_t
到C ++中是一个错误,对C ++ 0x的Unicode添加也是如此。但是,STL实现必须要求将每个std::string
或char*
参数都视为与Unicode兼容。
我也反对“ 使用您想要的 ”方法。我认为没有这种自由的理由。文本主题上有足够的混乱,导致所有这些损坏的软件。综上所述,我相信程序员必须最终就UTF-8达成共识,这是一种正确的方法。(我来自一个不讲阿拉伯语的国家,并且在Windows上长大,因此我最后一次基于宗教理由会攻击UTF-16)。
我想分享更多有关如何在Windows上执行文本以及为编译时检查的unicode正确性,易用性和更好的代码多平台性向其他所有人推荐的信息。该建议与通常建议的在Windows上使用Unicode的正确方法大不相同。然而,对这些建议的深入研究得出了相同的结论。因此,这里去:
- 请勿在接受UTF-16的API的相邻位置使用
wchar_t
或std::wstring
在其他位置使用该API。
- 请勿使用
_T("")
或L""
UTF-16文字(作为UTF-16弃用的一部分,应将IMO排除在标准之外)。
- 请勿使用对
_UNICODE
常数敏感的类型,函数或其派生类,例如LPTSTR
或CreateWindow()
。
- 但是,
_UNICODE
始终进行定义,以避免将char*
字符串传递给WinAPI进行静默编译
std::strings
以及char*
程序中的任何位置都被视为UTF-8(如果未另行说明)
- 我的所有字符串都是
std::string
,尽管您可以将char *或字符串文字传递给convert(const std::string &)
。
仅使用接受widechars(LPWSTR
)的Win32函数。决不接受LPTSTR
或接受的人LPSTR
。通过这种方式传递参数:
::SetWindowTextW(Utils::convert(someStdString or "string litteral").c_str())
(该策略使用下面的转换函数。)
使用MFC字符串:
CString someoneElse; // something that arrived from MFC. Converted as soon as possible, before passing any further away from the API call:
std::string s = str(boost::format("Hello %s\n") % Convert(someoneElse));
AfxMessageBox(MfcUtils::Convert(s), _T("Error"), MB_OK);
在Windows上使用文件,文件名和fstream:
- 从来没有过
std::string
或const char*
文件名参数,以fstream
家庭。MSVC STL不支持UTF-8参数,但具有非标准扩展名,应按以下方式使用:
将std::string
参数转换为std::wstring
with Utils::Convert
:
std::ifstream ifs(Utils::Convert("hello"),
std::ios_base::in |
std::ios_base::binary);
当MSVC的态度fstream
发生变化时,我们将必须手动删除转换。
- 该代码不是多平台的,将来可能需要手动更改
- 有关
fstream
更多信息,请参见unicode研究/讨论案例4215。
- 切勿产生非UTF8内容的文本输出文件
- 避免
fopen()
出于RAII / OOD原因使用。如有必要,请使用_wfopen()
上面的和WinAPI约定。
// For interface to win32 API functions
std::string convert(const std::wstring& str, unsigned int codePage /*= CP_UTF8*/)
{
// Ask me for implementation..
...
}
std::wstring convert(const std::string& str, unsigned int codePage /*= CP_UTF8*/)
{
// Ask me for implementation..
...
}
// Interface to MFC
std::string convert(const CString &mfcString)
{
#ifdef UNICODE
return Utils::convert(std::wstring(mfcString.GetString()));
#else
return mfcString.GetString(); // This branch is deprecated.
#endif
}
CString convert(const std::string &s)
{
#ifdef UNICODE
return CString(Utils::convert(s).c_str());
#else
Exceptions::Assert(false, "Unicode policy violation. See W569"); // This branch is deprecated as it does not support unicode
return s.c_str();
#endif
}