Why does .net uses the UTF16 encoding for string , but uses utf8 as default for saving files?
从这里
Essentially, string uses the UTF-16 character encoding form
但是当保存vs streamwriter时:
This constructor creates a StreamWriter with UTF-8 encoding without a
Byte-Order Mark (BOM),
我看到这个示例(断开的链接被删除):
有些字符串的utf8较小,有些字符串的utf-16较小。
- 那么为什么.NET使用utf16作为字符串的默认编码,而utf8用于保存文件?
谢谢您。
我已经读过那篇著名的文章了
- 埃里克·利珀特的这篇文章更详细地阐述了做出决定的原因。
- @卢卡佐伊德的文章很棒,但请注意这些评论,汉斯·帕桑特不同意一个令人信服的论点。
- @lukazoid's link的工作版本:web.archive.org/web/20161121052650/http://blog.coverity.com/‌&误8203;…
- 简而言之,utf16不可移植,而utf8是超级可移植的。
如果你很乐意忽略代理对(或者相当于,你的应用程序可能需要基本多语言平面以外的字符),utf-16有一些很好的属性,基本上是因为每个代码单元都需要两个字节,并且在一个代码单元中表示所有BMP字符。
考虑原始类型char。如果我们使用UTF-8作为内存中的表示,并且希望处理所有Unicode字符,那么它应该有多大?最多可以有4个字节…这意味着我们必须分配4个字节。在这一点上,我们最好使用UTF-32!
当然,我们可以使用utf-32作为char表示,但是在string表示中使用utf-8,并按我们的方式转换。
UTF-16的两个缺点是:
- 每个Unicode字符的代码单位数是可变的,因为并非所有字符都在BMP中。直到emoji变得流行,这并没有影响很多日常使用的应用程序。现在,当然对于消息应用程序等,使用UTF-16的开发人员确实需要了解代理对。
- 对于纯ASCII(很多文本,至少在西方是这样),它需要相当于UTF-8编码文本两倍的空间。
(顺便说一句,我相信Windows对Unicode数据使用UTF-16,而且.NET也有必要根据互操作的原因采用这种方法。但这只会把问题推到一步。)
考虑到代理对的问题,我怀疑如果一种语言/平台是从零开始设计的,没有互操作要求(但是基于Unicode的文本处理),那么UTF-16将不是最佳选择。无论是UTF-8(如果你想提高内存效率,并且不介意处理复杂度达到第n个字符),还是UTF-32(反过来说)都是一个更好的选择。(甚至进入第n个字符也有"问题",这是因为不同的规范化形式。文本很难…)
- UTF-8的要点是,如果每个字符需要6个字节才能真正表示所有可能的情况,那么任何低于UTF-32的情况都是一个需要特殊情况和额外代码的问题。所以utf-16和utf-8都不完美。但是,由于UTF-8只有一半大小,所以您也可以使用它。通过使用UTF-16,您什么也得不到(除了增加的文件/字符串大小)。当然,有些人会使用UTF-16,而忽略了它会处理所有字符。
- 您能详细介绍一下"在字符串表示中使用UTF-8,并在进行转换"吗?它们(utf8,16)的宽度都是可变的…
- 我已经读了14遍了。但我还是不明白这一行:每个代码单元的大小是恒定的。afaik的大小可以是2,3,4字节(UTF-16),那么这里的常量是什么?
- 我认为他是指ucs-16,Windows称之为"unicode",即固定的每字符2字节编码。当时,我们认为这足以存储所有字符编码。我们错了,因此UTF-8现在是互联网的"标准"。
- @gbjbaanb:no,.net使用utf-16。因此,当需要BMP之外的任何内容时,将使用代理项对。每个字符都是一个UTF-16代码单元。(据我所知,也没有ucs-16这样的东西——我认为你的意思是ucs-2。)
- @罗伊纳米尔:不,UTF-16代码单元的大小总是2字节。Unicode字符采用一个代码单位(对于基本多语言平面)或两个代码单位(对于字符U+10000及以上)。
- 谢谢乔恩。我以为你忘了我……现在很清楚了。再次感谢。
- 但是jon,在我的问题中查看表时,假设"hello world"保存在一个XML文件中,该文件是用utf 8编码保存的。稍后,我在vs中打开该文件,并执行(!)看到XML了吗?"你好,世界"--所以,Visual Studio eFitor知道!!)如何打开文件。它知道如何解码硬盘上的字节。那么——为什么我还需要在XML的顶部声明字符集编码标记?
- @Royinamir:特别是XML,如果您使用的是UTF-8或UTF-16,则不需要有编码标签。规范解释了如何从前几个字符推断编码。对于任何其他编码,必须包括编码。(请注意,您的问题没有提到XML Anywhere…)
- 乔恩,对不起,为什么其他编码不同?我的意思是,如果我的程序以字节的形式读取一个远程文件,并且可以从第一个字节推断编码,那么为什么还要在标记处再次提到它呢?我觉得奇怪的是,我可以通过线索打开保险箱(第一个字节),当我打开它时,我又看到里面的线索(charset标签)。我这里一定有东西丢了。:
- @Royinamir:它只能在utf-8和utf-16之间进行推断,而这些是XML规范规定的唯一可以忽略的。而这仅仅是针对XML——对于其他文本文件,编辑器只需进行试探性的猜测,就会出错。
- @乔恩斯基特:但是如果他们能弄错(假设他们弄错了),他们怎么知道"正确读取"<...charset=...部分的编码数据?(谢谢你的回答。我没有找到任何文章来回答我的最新问题。)
- @罗伊纳米尔:老实说,这应该是一个新问题,因为它是XML特有的。但我相信有一种假设,即其他编码将与ASCII兼容,但我怀疑支持非ASCII兼容编码的XML解析器也可以尝试这些编码。有关详细信息,请参阅w3.org/tr/xml/charencoding。
- @琼斯基特:我错过了什么?据我所知,utf-16可以是2或4字节。所有Internet资源都显示相同的内容:wiki或unicode.org
- @gmorphus:utf-16代码单元总是2个字节。一个Unicode代码点由一个或两个UTF-16代码单元表示。我不确定你对答案或评论的哪一部分有异议。
- @Jonskeet"最多6个字节"。在汤普森-派克(Thompson-Pike)的UTF-8方案(Ken Thompson和Rob-Pike)中,字符的可设置范围是[0,7fffffffff],最多需要6个字节(或八位字节:8位字节)。2003年,字符的范围被限制为[0,10ffff](UTF-16可访问范围)。请参见:tools.ietf.org/html/rfc3629,所有字符都使用1到4个八位字节的序列进行编码。不是6。
- @罗伊纳米尔·琼斯基特说:"(UTF8,16)的宽度是可变的。"我明白他的意思是UTF-16不是一种可变宽度的编码,他是对的。您回答:"UTF-16代码单元的大小总是2字节"。而且…,UTF-8代码单元的大小总是1字节。
- @Fernandopelliccioni:如何精确定义"可变宽度编码"?刚刚重读了定义,我同意我对"代码单元"的精确含义感到困惑,但是UTF-8和UTF-16都是可变宽度,即"它们可以使用可变字节数来表示单个Unicode代码点"。对于utf-8是1-4字节,对于utf-16是2或4字节。现在将检查我的其余答案的准确性。
- @Fernandopelliccioni:我已经修复了"最多6个字节的部分"btw。
- @费尔南多·奥佩利奇奥尼:谢谢你的建议,顺便说一句,而且总是很高兴能更准确地了解术语。
- 谢谢你@jonsket。你总是很乐意用你的知识帮助别人。以下是一些我认为很好的参考资料。(超出标准)utf8everywhere.org programmers.stackexchange.com/questions/102205/&hellip;
- @在这里,Jonskeet是Unicode成员对"可变宽度编码"含义的另一个引用。unicode.org/versions/unicode8.0.0/unicodestandard-8.0.pdf(参见第[36-39]页)
- @Fernandopelliccioni:是的,这也同意UTF-16是可变宽度的。"用一个或两个16位代码单元表示的字符之间的区别意味着正式的UTF-16是一种可变宽度的编码形式。"
- 让我们在聊天中继续讨论。
正如许多"为什么选择"的问题一样,这是由历史决定的。Windows在1993年成为其核心的Unicode操作系统。当时,Unicode仍然只有65535个码位,这些日子被称为ucs。直到1996年,Unicode才获得了将编码空间扩展到一百万个码位的补充平面。以及代理对,以使它们适合于16位编码,从而设置UTF-16标准。
.NET字符串是UTF-16,因为它非常适合操作系统编码,不需要转换。
UTF-8的历史更为模糊。绝对超过Windows NT,RFC-3629的日期是1993年11月。花了一段时间才站稳脚跟,互联网就是工具。
UTF-8是文本存储和传输的默认格式,因为它对大多数语言都是相对紧凑的格式(有些语言在UTF-16中比在UTF-8中更紧凑)。每种特定的语言都有一种更有效的编码。
UTF-16用于内存中的字符串,因为每个字符解析和直接映射到Unicode字符类和其他表的速度更快。Windows中的所有字符串函数都使用UTF-16,并且使用了多年。