需要帮助理解UTF编码

时间:2011-06-11 04:14:41

标签: c# encoding utf-8 utf-16 utf

你好,我注意到当我使用UTF-8编码(没有BOM)保存文本文件时,我能够在C#上使用UTF-16编码完美地读取它。现在这让我有点困惑,因为UTF-8只使用了8位,对吧?而utf-16对每个字符都需要16位。

现在想象一下,我把这个文件中的字符串“ab”写成UTF-8,然后那里有一个字母“a”&另一个用于“b”。

好的,但是在使用UTF-16字符集时如何读取此UTF-8文件?我看到它的方式,在读取文件时,“ab”的两个字节将被误认为只包含两个字节的一个字符。因为UTF-16需要那2个字节。

这就是我读它的方式(t.txt被编码为UTF-8):

using(StreamReader sr = new StreamReader(File.OpenRead("t.txt"), Encoding.GetEncoding("utf-16")))
{
    Console.Write(sr.ReadToEnd());
    Console.ReadKey();
}

3 个答案:

答案 0 :(得分:5)

查看http://www.joelonsoftware.com/articles/Unicode.html,它将回答您的所有unicode问题

答案 1 :(得分:1)

The '8' means it uses 8-bit blocks to represent a character.这并不意味着每个字符都需要固定的8位。每个字符的块数从1到4不等(尽管字符长度可以达到6个字节)。

尝试这个简单的测试,

  • 使用没有BOM编码的UTF8创建文本文件(例如Notepad ++)
  • 使用File.ReadAllBytes()阅读文本文件(正如您在代码中所做的那样)。 byte[] utf8 = File.ReadAllBytes(@"E:\SavedUTF8.txt");
  • 检查每个字符占用的字节数。
  • 现在尝试使用编码为ANSI byte[] ansi = File.ReadAllBytes(@"E:\SavedANSI.txt");
  • 的文件
  • 比较两种编码的每个字符的字节数。

注意,File.ReadAllBytes()尝试根据字节顺序标记的存在自动检测文件的编码。可以检测到编码格式UTF-8和UTF-32(big-endian和little-endian)。


有趣的结果
SavedUTF8.txt包含字符

  • a:字节数组中的字节数= 1 1 byte per character
  • ©(UTF + 00A9)(Alt + 0169):字节数组中的字节数= 2 2 bytes per character
  • :( UTF + E0A080)(Alt + 14721152)字节数组中的字节数= 3 3 bytes per character

ANSI编码总是需要8位(即在上面的示例中,无论文件中的字符如何,字节数组总是大小为1)。正如@tchrist所指出的,UTF16每个字符占用2或4个字节(而不是每个字符固定的2个字节)。


编码表(来自here
以下字节序列用于表示字符。要使用的序列取决于字符的Unicode编号:

U-00000000 – U-0000007F:    0xxxxxxx
U-00000080 – U-000007FF:    110xxxxx 10xxxxxx
U-00000800 – U-0000FFFF:    1110xxxx 10xxxxxx 10xxxxxx
U-00010000 – U-001FFFFF:    11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
U-00200000 – U-03FFFFFF:    111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
U-04000000 – U-7FFFFFFF:    1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

xxx 位位置用二进制表示中的字符代码编号的位填充。最右边的 x 位是最低有效位。只能使用可以表示字符代码号的最短可能的多字节序列。请注意,在多字节序列中,第一个字节中前导1位的数量与整个序列中的字节数相同。


确定角色的大小

  

表示非ASCII字符的多字节序列的第一个字节始终在0xC0到0xFD的范围内,它表示该字符的后续字节数。

这意味着2字节字符(110)的前导位与3字节字符(1110)的前导位不同。这些前导位可用于唯一标识字符所占的字节数。


更多信息

答案 2 :(得分:1)