【问题标题】:Good resources for learning the different types of Character Encoding and converting between them学习不同类型的字符编码并在它们之间转换的好资源
【发布时间】:2009-09-11 11:09:51
【问题描述】:

我从未真正理解过的一件事是字符编码的概念。在内存和代码中处理编码的方式常常让我感到困惑,因为我只是从互联网上复制了一个示例,而没有真正理解它的作用。我觉得这是一个非常重要且被忽视的主题,更多的人应该花时间去纠正(包括我自己)。

我正在寻找一些好的资源来学习不同类型的字符编码并在它们之间进行转换(最好在 C# 中)。欢迎书籍和在线资源。

谢谢。


编辑 1:

感谢您迄今为止的回复。我特别在寻找更多涉及 .NET 如何处理编码的信息。我知道这可能看起来很模糊,但我真的不知道要问什么。我想我很好奇在 C# 字符串类中编码是如何表示的,以及该类本身是否可以管理不同的编码类型或者有单独的类?

【问题讨论】:

    标签: .net encoding internationalization character-encoding globalization


    【解决方案1】:

    我会从这个问题开始:什么是字符?

    • 逻辑标识:代码点。 Unicode 为每个字符分配一个数字,该数字不一定与任何位/字节形式相关。编码(如 UTF-8)定义到字节值的映射。
    • 位和字节:编码形式。每个代码点一个或多个字节,值由使用的编码确定。
    • 您在屏幕上看到的东西:字形。字形由一个或多个代码点创建。这是演示结束时的内容。

    此代码将in.txtwindows-1252 转换为UTF-8 并将其保存为out.txt

    using System;
    using System.IO;
    using System.Text;
    public class Enc {
      public static void Main(String[] args) {
        Encoding win1252 = Encoding.GetEncoding(1252);
        Encoding utf8 = Encoding.UTF8;
        using(StreamReader reader = new StreamReader("in.txt", win1252)) {
          using(StreamWriter writer = new StreamWriter("out.txt", false, utf8)) {
            char[] buffer = new char[1024];
            while(reader.Peek() > 0) {
              int r = reader.Read(buffer, 0, buffer.Length);
              writer.Write(buffer, 0, r); 
            }
          }
        }
      }
    }
    

    这里发生了两个转变。首先,字节从windows-1252 解码到UTF-16(我认为是小端序)到char 缓冲区。然后将缓冲区转换为UTF-8

    代码点

    一些示例代码点:

    • U+0041 是 拉丁文大写字母 A (A)
    • U+00A3 是 磅符号 (£)
    • U+042F 是 西里尔大写字母 YA (Я)
    • U+1D50A 是 MATHEMATICAL FRAKTUR CAPITAL G (?)

    编码

    在您使用字符的任何地方,它都会采用某种形式的编码。 C# 使用 UTF-16 作为其 char type,它定义为 16 位宽。

    您可以将编码视为代码点和字节表示之间的表格映射。

    CODEPOINT       UTF-16BE        UTF-8     WINDOWS-1252
    U+0041 (A)         00 41           41               41
    U+00A3 (£)         00 A3        C2 A3               A3
    U+042F (Ya)        04 2F        D0 AF                -
    U+1D50A      D8 35 DD 0A  F0 9D 94 8A                -
    

    System.Text.Encoding 类公开类型/方法来执行转换。

    字形

    您在屏幕上看到的字形可能由多个代码点构成。字符 e-acute (é) 可以用两个代码点表示,LATIN SMALL LETTER E U+0065 和 COMBINING ACUTE ACCENT U+0301。

    ('é' 通常由单个代码点 U+00E9 表示。您可以使用规范化在它们之间切换。但并非所有组合序列都具有单个字符等效项。)

    结论

    • 当您将 C# 字符串编码为编码时,您正在执行从 UTF-16 到该编码的转换。
    • 编码可能是一种有损转换 - 大多数非 Unicode 编码只能编码现有字符的子集。
    • 由于并非所有代码点都可以放入单个 C# 字符中,因此字符串中的字符数可能多于代码点数,并且代码点数可能大于呈现的字素数。
    • 字符串的“长度”是上下文相关的,因此您需要知道所应用的含义并使用适当的算法。处理方式取决于您使用的编程语言。
    • 在许多编码中为 Latin-1 字符赋予相同的值会使一些人产生 ASCII 错觉。

    (这比我预期的要啰嗦一点,而且可能比你想要的要多,所以我会停下来。我写了一个更啰嗦的post on Java encoding here。)

    【讨论】:

    • 谢谢 McDowell,这正是我正在寻找的东西。
    【解决方案2】:

    维基百科对字符编码有一个很好的解释:http://en.wikipedia.org/wiki/Character_encoding

    如果您正在寻找最流行的字符编码之一 UTF-8 的详细信息,您应该阅读UTF-8 and Unicode FAQ

    而且,正如已经指出的那样,"The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)" 是一个非常好的初学者教程。

    【讨论】:

      【解决方案3】:

      有著名的 Joel 文章“每个软件开发人员绝对、肯定必须了解 Unicode 和字符集的绝对最低要求(没有借口!)” http://www.joelonsoftware.com/articles/Unicode.html

      编辑:虽然这更多的是关于文本格式,但在重新阅读时,我猜你对 html 编码和 url 编码之类的东西更感兴趣?用于转义在 html 或 url 中具有重要意义的特殊字符(例如 在 html 中,或 ? 和 = 在 url 中)

      【讨论】:

        猜你喜欢
        • 2011-01-04
        • 1970-01-01
        • 2010-12-04
        • 2018-04-29
        • 1970-01-01
        • 1970-01-01
        • 2010-11-20
        • 2010-11-25
        • 2010-11-27
        相关资源
        最近更新 更多