我一直在读一些关于Unicode的主题 - 特别是UTF-8 - (非)支持C++ 11,我希望Stack Overflow上的大师可以向我保证我的理解是正确的,或指出我在哪里误解或错过了某些情况.
首先,好的:您可以在源代码中定义UTF-8,UTF-16和UCS-4文字.此外,<locale>标头包含几个std::codecvt可以在UTF-8,UTF-16,UCS-4和平台多字节编码之间进行转换的实现(虽然API看起来很温和,但不是直截了当).这些codecvt实现可以imbue()在流上进行,以允许您在读取或写入文件(或其他流)时进行转换.
[ 编辑: Cubbi在评论中指出我忽略了提到<codecvt>标题,它提供了std::codecvt不依赖于语言环境的实现.此外,std::wstring_convert和wbuffer_convert函数可以使用这些codecvt来直接转换字符串和缓冲区,而不是依赖于流.
C++ 11还包括C99/C11 <uchar.h>标头,其中包含将来自平台多字节编码(可能是或不是UTF-8)的单个字符转换为UCS-2和UCS-4的功能.
但是,这是关于它的程度.虽然你当然可以将UTF-8文本存储在a中std::string,但我无法看到任何对它有用的东西.例如,除了在代码中定义文字之外,您不能将字节数组验证为包含有效的UTF-8,您无法找到长度(即Unicode字符的数量,对于某些"字符"的定义)包含UTF-8 std::string,并且不能std::string以字节为单位以任何方式迭代a .
同样,即使添加C++ 11 std::u16string也不支持UTF-16,但只支持较旧的UCS-2 - 它不支持代理对,只留下BMP.
鉴于UTF-8是在几乎所有Unix派生系统(包括Mac OS X和*Linux)上处理Unicode的标准方式,并且已经在很大程度上成为Web上事实上的标准,现代C++中缺乏支持似乎像一个相当严重的遗漏.即使在Windows上,新std::u16string功能并不真正支持UTF-16 这一事实似乎有些令人遗憾.
*由于在评论中指出,并明确提出在这里的Mac OS使用UTF-8的BSD衍生的部分,而可可使用UTF-16.
如果你设法阅读了所有这些,谢谢!只是几个简单的问题,因为这毕竟是Stack Overflow ...
以上分析是否正确,或者我是否缺少任何其他支持Unicode的设施?
在过去几年中,标准委员会在快速推进C++方面做得非常出色.他们都很聪明,我认为他们很清楚上述缺点.是否有一个众所周知的原因,即Unicode支持在C++中仍然很差?
展望未来,是否有人知道有任何纠正这种情况的建议?快速搜索isocpp.org似乎没有透露任何信息.
编辑:感谢大家的回复.我不得不承认,我发现它们有点令人沮丧 - 看起来现状在不久的将来不太可能改变.如果在认知方面存在共识,似乎完全的Unicode支持太难了,并且任何解决方案必须重新实现大多数ICU才被认为是有用的.
我个人不同意这一点; 我认为可以找到有价值的中间立场.例如,对于UTF-8和UTF-16的验证和归一化算法是由Unicode财团以及指定的,并且可以通过标准库中,比方说自由函数,一个被提供std::unicode的命名空间.仅这些对于需要与期望Unicode输入的库接口的C++程序来说是一个很大的帮助.但基于下面的答案(微笑,必须说,带着一丝苦涩),似乎Puppy关于这种有限功能的提议并不受欢迎.
我正在努力获取unicode字符串的数量,并尝试了各种选项.看起来像一个小问题,但在很大程度上受到了打击.
在这里,我试图获得字符串str1的长度.我得到它6.但实际上它是3.将光标移动到字符串"குமார்"也显示为3个字符.
基本上我想测量长度并打印每个角色.喜欢"கு","மா","ர்".
public class one {
public static void main(String[] args) {
String str1 = new String("??????");
System.out.print(str1.length());
}
}
Run Code Online (Sandbox Code Playgroud)
PS:这是泰米尔语.
一点前景:我的任务需要将UTF-8 XML文件转换为UTF-16(当然还有正确的标题).所以我搜索了将UTF-8转换为UTF-16的常用方法,并发现应该使用来自的模板<codecvt>.
但现在当它被弃用时,我想知道执行相同任务的新常用方法是什么?
(根本不介意使用Boost,但除此之外我更喜欢尽可能靠近标准库.)
我在Java的内部表示中搜索了String,但我有两种看起来可靠但不一致的材料.
一个是:
http://www.codeguru.com/cpp/misc/misc/multi-lingualsupport/article.php/c10451
它说:
Java使用UTF-16作为内部文本表示,并支持对字符串序列化进行非标准的UTF-8修改.
另一个是:
它说:
Tcl也使用与Java相同的修改后的UTF-8 [25]来表示Unicode数据,但对外部数据使用严格的CESU-8.
修改过的UTF-8?还是UTF-16?哪一个是正确的?Java在内存中使用了多少字节?
请让我知道哪一个是正确的以及它使用了多少字节.
我正在尝试插入XML列(SQL SERVER 2008 R2),但服务器抱怨:
System.Data.SqlClient.SqlException(0x80131904):
XML解析:第1行,第39个字符,无法切换编码
我发现XML列必须是UTF-16才能使插入成功.
我正在使用的代码是:
XmlSerializer serializer = new XmlSerializer(typeof(MyMessage));
StringWriter str = new StringWriter();
serializer.Serialize(str, message);
string messageToLog = str.ToString();
Run Code Online (Sandbox Code Playgroud)
如何将对象序列化为UTF-8字符串?
编辑:好的,抱歉混淆 - 字符串需要是UTF-8.你是对的 - 默认情况下它是UTF-16,如果我尝试以UTF-8插入它就会通过.所以问题是如何序列化为UTF-8.
例
这会在尝试插入SQL Server时导致错误:
<?xml version="1.0" encoding="utf-16"?>
<MyMessage>Teno</MyMessage>
Run Code Online (Sandbox Code Playgroud)
这不是:
<?xml version="1.0" encoding="utf-8"?>
<MyMessage>Teno</MyMessage>
Run Code Online (Sandbox Code Playgroud)
更新
我想出当SQL Server 2008的Xml列类型需要utf-8时,以及当encoding你尝试插入xml规范的属性中的utf-16时:
如果要添加utf-8,请将参数添加到SQL命令,如下所示:
sqlcmd.Parameters.Add("ParamName", SqlDbType.VarChar).Value = xmlValueToAdd;
Run Code Online (Sandbox Code Playgroud)
如果您尝试encoding=utf-16在上一行中添加xmlValueToAdd,则会在插入中产生错误.此外,VarChar意味着国家字符不被识别(它们变成问号).
要将utf-16添加到db,请使用SqlDbType.NVarChar或SqlDbType.Xml在前面的示例中,或者根本不指定type:
sqlcmd.Parameters.Add(new SqlParameter("ParamName", xmlValueToAdd));
Run Code Online (Sandbox Code Playgroud) BMP是基本的多语言平面
根据JavaScript:好的部分:
JavaScript是在16位字符集的时候构建的,因此JavaScript中的所有字符都是16位宽.
这让我相信JavaScript使用UCS-2(不是UTF-16!)并且只能处理U + FFFF以前的字符.
进一步调查证实了这一点:
> String.fromCharCode(0x20001);
Run Code Online (Sandbox Code Playgroud)
fromCharCode返回Unicode字符时,该方法似乎只使用最低16位.试图获得U + 20001(CJK统一表意文字20001)而不是返回U + 0001.
问题:是否可以在JavaScript中处理后BMP字符?
2011-07-31:来自Unicode支持Shootout的第 12个幻灯片:好的,坏的,以及(大部分)Ugly很好地解决了与此相关的问题:

假设程序在具有UTF-16编码字符集的系统上运行.所以根据C++编程语言 - 第4页,第150页:
char可以保存机器字符集的字符.
→我认为char变量的大小是2字节.
但根据ISO/IEC 14882:2014:
sizeof(char),sizeof(signed char)并且sizeof(unsigned char)是1".
或者C++编程语言 - 第4页,第149页:
"[...],所以根据定义,char的大小是1"
→固定尺寸为1.
问题:上述这些语句之间是否存在冲突,或者sizeof(char) = 1只是默认(定义)值,并且实现定义取决于每个系统?
我有一个大学编程考试,一个部分是关于unicode.
我已经检查了所有的答案,我的讲师没用,所以没有帮助,所以这是你们可能提供帮助的最后手段.
问题将是这样的:
字符串'mЖ丽'具有这些unicode代码点
U+006D,U+0416并且U+4E3D使用十六进制编写的答案,手动将字符串编码为UTF-8和UTF-16.
任何帮助都将非常感激,因为我试图让我的头脑.
如何输入Unicode字符, without copying it to the clipboard and pasting it?
Things I know:
ga角色上的命令 gives me hex:0001d4ed."+p.<C-v>u例如<C-v>u03b1给出?字符.如果我将一个角色转换为byte然后再回到char那个角色,那个角色会神秘地消失并成为别的东西.这怎么可能?
这是代码:
char a = 'È'; // line 1
byte b = (byte)a; // line 2
char c = (char)b; // line 3
System.out.println((char)c + " " + (int)c);
Run Code Online (Sandbox Code Playgroud)
一直到第2行一切都很好:
在第1行,我可以在控制台中打印"a",它会显示"È".
在第2行,我可以在控制台中打印"b",它会显示-56,即200,因为字节已签名.200是"È".所以它仍然很好.
但第3行有什么不对?"c"成为别的东西,程序打印出来? 65480.这是完全不同的东西.
我应该在第3行写什么才能得到正确的结果?