• .NET:字符集和编码学习总结


    背景

    一直没有深入的学习字符集和编码的知识(现在也没有深入),今天查阅了一些资料,弄明白了一些事情,本文就简单记录一下。

    字符集和编码

    字符集是指一些符号组成的集合,编码是对指定字符集如何表示为字节的一种规则,一个字符集可以由多种编码。

    参考文章:http://www.cnblogs.com/skynet/archive/2011/05/03/2035105.html

    .NET支持多少种编码?默认编码是什么?

    测试程序

    1         public static void 打印所有编码规则总数()
    2         {
    3             Console.WriteLine(string.Format("系统支持【{0}】条编码规则。", Encoding.GetEncodings().Count()));
    4         }
    5 
    6         public static void 打印默认编码规则()
    7         {
    8             Console.WriteLine(string.Format("系统默认编码规则:【{0}】。", Encoding.Default.EncodingName));
    9         }

    输出结果

    注:系统的默认编码和操作系统的语言环境有关系,我是中文操作系统,所以这里的输出是:GB2312。

    .NET中使用何种编码表示字符串?

    这个问题和源代码所在的文件的编码没有任何关系,文件的格式只是影响开发期间的编程工作,如:采用ASCII编码的文件不能使用中文变量名。

    因为Char的内部表示和Short是一样的,所以不难想象.NET使用的是Unicode的16位编码,让我们测试一下。

    测试程序

     1         public static void 语言的字符串采用的编码()
     2         {
     3             Console.WriteLine("
    ***" + System.Reflection.MethodInfo.GetCurrentMethod().Name + "***");
     4 
     5             string originalString = "hi 段";
     6 
     7             Console.WriteLine(
     8                 String.Join(
     9                     ",",
    10                     originalString
    11                     .SelectMany(x => new byte[] { (byte)(x), (byte)(x >> 8) })
    12                     .Select(x => Convert.ToString(x, 16))
    13                 )
    14             );
    15 
    16             Console.WriteLine(
    17                 String.Join(
    18                     ",",
    19                     Encoding.Unicode
    20                     .GetBytes(originalString)
    21                     .Select(x => Convert.ToString(x, 16))
    22                 )
    23             );
    24 
    25             Console.WriteLine(
    26                 String.Join(
    27                     ",",
    28                     Encoding.UTF8
    29                     .GetBytes(originalString)
    30                     .Select(x => Convert.ToString(x, 16))
    31                 )
    32             );
    33 
    34             Console.WriteLine(
    35                 String.Join(
    36                     ",",
    37                     Encoding.UTF32
    38                     .GetBytes(originalString)
    39                     .Select(x => Convert.ToString(x, 16))
    40                 )
    41             );
    42         }

    输出结果

    一些错误的编码使用场景

    编码和解码使用不同的规则

    测试代码

     1         public static void 将string转换为byte数组和将byte数组转换为string采用不同的编码规则()
     2         {
     3             Console.WriteLine("
    ***" + System.Reflection.MethodInfo.GetCurrentMethod().Name + "***");
     4 
     5             string originalString = "Hello Test, 测试!";
     6 
     7             byte[] utf8Bytes = Encoding.UTF8.GetBytes(originalString);
     8             string errorString = Encoding.ASCII.GetString(utf8Bytes);
     9 
    10             Console.WriteLine("原始字符串:【{0}】。", originalString);
    11             Console.WriteLine("用UTF8编码,用ASCII解码后的错误字符串:【{0}】。", errorString);
    12         }

    输出结果

    使用的编码规则对应的字符集不支持字符串拥有的字符

    测试程序

     1         public static void 将string转换为byte数组使用了错误了编码规则()
     2         {
     3             Console.WriteLine("
    ***" + System.Reflection.MethodInfo.GetCurrentMethod().Name + "***");
     4 
     5             string originalString = "Hello Test, 测试!";
     6 
     7             byte[] asciiBytes = Encoding.ASCII.GetBytes(originalString);
     8             string errorString = Encoding.ASCII.GetString(asciiBytes);
     9 
    10             Console.WriteLine("原始字符串:【{0}】。", originalString);
    11             Console.WriteLine("用ASCII编码,用ASCII解码后的错误字符串:【{0}】,因为字符串中包含非ASCII字符。", errorString);
    12         }

    输出结果

    ANSI在中文操作系统下原来是GB2212

    昨晚以为ANSI是采用ASCII编码,早上经群里的朋友斧正,原来是根据不同的环境会采用不同的编码,中文操作系统多少是GB2312。

    测试程序

    1         public static void 读取包含了ANSI字符的ANSI编码文件()
    2         {
    3             Console.WriteLine("
    ***" + System.Reflection.MethodInfo.GetCurrentMethod().Name + "***");
    4 
    5             var file = @"E:CodingHappyStudyEncodingStudyEncodingStudyANSI.txt";
    6             Console.WriteLine("使用GB2312编码读取的内容:" + File.ReadAllText(file, Encoding.GetEncoding("GB2312")));
    7         }

    如何在不同的编码规则之间进行转换呢?

    程序中的字符串使用是采用Unicode进行编码的,我们指的编码转换多少是指不同的IO流之间的转换,简单的思路是:

    1. 将“源流”转换为.NET字符串(Unicode)编码。
    2. 将.NET字符串以目标编码写入“目标流”。

    注:应该有快捷的算法在字节级别直接在两种编码规则之间做映射的,这里没有深究。

    能自动识别文件编码吗?

    为什么.NET没有提供自动识别文件编码的功能?估计是没法支持,现实确实是没法支持,具体来说是只能支持个别编码的自动识别,原理参考这篇文章:http://blog.csdn.net/lipeijs3/article/details/5062243

    备注

    .NET中处理编码还是比较舒服的,改天得看看动态语言是如何处理的,等几天写一篇Ruby相关的编码文章。

  • 相关阅读:
    JQ对JSON的增删改
    Debug编辑通过转Release找不到命名空间
    Codeforces Round #740(Div. 2)
    2021“MINIEYE杯”中国大学生算法设计超级联赛(10)
    2021“MINIEYE杯”中国大学生算法设计超级联赛(8)
    Codeforces Round #737 (Div. 2)
    2021“MINIEYE杯”中国大学生算法设计超级联赛(7)
    2021牛客暑期多校训练营8
    2021牛客暑期多校训练营7
    2021“MINIEYE杯”中国大学生算法设计超级联赛(6)
  • 原文地址:https://www.cnblogs.com/happyframework/p/3273606.html
Copyright © 2020-2023  润新知