了解编码

更新:2007 年 11 月

.NET Framework 在内部将文本存储为 Unicode UTF-16 格式。编码器将此文本数据转换成字节序列。解码器将字节序列转换成此内部格式。编码描述了编码器或解码器的操作规则。例如,UTF8Encoding 类描述了对以 Unicode UTF-8 格式表示的文本的字节序列的编码和解码规则。编码和解码过程还可以包含某些验证步骤。例如,UnicodeEncoding 类会检查所有代理项,以确保它们构成有效的代理项对。这两个类都是从 Encoding 类继承的。

选择编码

Unicode 标准为所支持的每个脚本中的每个字符分配一个码位(一个数字)。Unicode 转换格式 (UTF) 是一种码位编码方式。有关 System.Text 中的类所支持的 UTF 的更多信息,请参见 .NET Framework 中的 Unicode 中的“使用 Unicode 编码”。

选择编码类

Encoding 类的使用非常广泛。使用受支持的继承自 Encoding 的类,.NET 应用程序可以与在旧式应用程序中可能遇到的常见编码一起工作,并且您还可以实现其他编码。不过,当您有机会选择编码时,强烈建议您使用 Unicode 编码,通常为 UTF8EncodingUnicodeEncoding(也支持 UTF32Encoding)。尤其需要指出的是,UTF8EncodingASCIIEncoding 更为可取。如果内容是 ASCII,则这两种编码是相同的,但 UTF8Encoding 还可以表示每个 Unicode 字符,而 ASCIIEncoding 仅支持介于 U+0000 和 U+007F 之间的 Unicode 字符值。因为 ASCIIEncoding 不提供错误检测,所以从安全角度来看,UTF8Encoding 也更好些。

UTF8Encoding 已经过优化以尽可能提高速度,它应比任何其他编码更快速。即使对于完全采用 ASCII 的内容,使用 UTF8Encoding 执行的操作也比使用 ASCIIEncoding 执行的操作速度更快。只有对某些旧式应用程序,才应考虑使用 ASCIIEncoding。但即使在这种情况下,UTF8Encoding 可能仍然是一种更好的选择。假定采用默认设置,将会出现以下情形:

  • 如果应用程序具有并非严格采用 ASCII 的内容,并使用 ASCIIEncoding 对其进行编码,则每个非 ASCII 字符都将被编码成一个问号(“?”)。如果应用程序随后对此数据进行解码,将会丢失信息。

  • 如果应用程序具有并非严格采用 ASCII 的内容,并使用 UTF8Encoding 对其进行编码,那么在将结果解释为 ASCII 时,结果看起来是不可理解的。但如果应用程序随后对此数据进行解码,数据能够成功还原。

选择回退策略

如果应用程序尝试对字符进行编码或解码,但不存在相应的映射,则应用程序必须实施回退策略(这是一种失败处理机制)。有两种类型的回退策略:

  1. 最佳回退

    当字符在目标编码/解码中不具有精确匹配时,应用程序可以尝试将它们映射到类似的字符。

  2. 替换字符串回退

    如果不存在合适的类似字符,则应用程序可以指定替换字符串。

例如,应用程序可以调用 GetEncoding(1252, 0, 0)(请参见 GetEncoding)。此调用通过将 encoderFallback 和 decoderFallback 指定为零来指定代码页 1252(用于西欧语言的 Windows 代码页)。对于某些 Unicode 字符,默认行为是最佳映射。例如,在对带圆圈的大写拉丁字母 S (U+24C8) 进行编码之前,会将其更改为大写拉丁字母 S (U+0053),并且将上标 5 (U+2075) 更改为数字 5 (U+0035)。如果应用程序随后从代码页 1252 向 Unicode 进行解码,则字母周围的圆圈将丢失,25 将变成 25。其他转换产生的变化可能更大。例如,Unicode 无限大符号 (U+221E) 可能会映射成数字 8 (U+0038)。

最佳策略随代码页的不同而有所变化,在此不加详细记录。例如,对于有些代码页,全角拉丁字符会映射成更常见的半角拉丁字符。对于其他代码页,不进行这种映射。

即使在积极的最佳策略中,在有些编码中仍然找不到适合某些字符的映射。例如,中文汉字不能合理地映射到代码页 1252。在这种情况下,将使用替换字符串。默认情况下,此字符串只是一个问号 (U+003F)。

对于 Encoding,最佳映射是默认行为,它将 Unicode 数据编码成代码页数据,有些旧式应用程序依赖于此行为。但是出于安全考虑,大多数新的应用程序应避免采用最佳行为。例如,应用程序不应对域名进行最佳编码。

应用程序应使用最佳映射的以下替代方式:

以下是对最佳编码(或解码)回退策略的两点进一步说明:

  • 在大多数情况下,最佳映射是一个编码问题而不是一个解码问题。有极少数代码页包含无法成功映射到 Unicode 的字符。因为这些字符不常用,所以 Unicode 中省略了它们。

  • 不存在对应于最佳回退的受支持的命名对象。每个代码页的最佳回退机制都各不相同。如果对于单个 Encoding 对象,应用程序需要在最佳回退和其他某个回退之间来回切换,则它应在对其他任何回退对象进行赋值之前,将原始的最佳回退对象复制到一个变量。然后,应用程序可以通过将该值重新赋给 Encoding.EncoderFallbackEncoding.DecoderFallback,恢复最佳回退。

请参见

任务

“回退”编码应用程序示例

参考

Decoding

DecoderFallback

Encoding

EncoderFallback

其他资源

编码和本地化