.NET基础 (08)字符串处理

字符串处理
1 System.String是值类型仍是引用类型
2 StringBuilder类型有何做用
3 如何在String和Byte[]对象之间进行转换
4 简述BASE64编码的做用以及C#中对其的支持
5 SecureString的实例如何被分配和释放
6 什么是字符串池机制算法

 

字符串处理
1 System.String是值类型仍是引用类型编程

System.String 是引用类型,它的对象在初始化后就不能再作修改,任何试图修改字符串对象的动做都将致使一个新的字符串对象的产生。设计模式

示例代码:数组

        static void Main(string[] args)
        {
            String a = "我是字符串";
            String b = a;
            Console.WriteLine(Object.ReferenceEquals(a, b));

            //尝试使用引用b修改a指向的对象
            b = "我是新的字符串";

            Console.WriteLine(a);
            Console.WriteLine(b);
            Console.WriteLine(Object.ReferenceEquals(a, b));
            Console.Read();
        }

输出结果:安全

True
我是字符串
我是新的字符串
False

性能


2 StringBuilder类型有何做用优化

String的性能问题产生于其内容不可修改的特性。当一个字符串对象被修改、插入、链接、截断是,新的字符串对象将被分配,这会影响性能。更加常见的状况是,一个字符串对象的最终生成须要通过一个组装过程,而在这个组装过程当中必将产生不少临时字符串对象。这些对象在堆上分配,须要垃圾回收器来回收,这些动做会对程序产生巨大的影响。而事实上,在字符串组装过程当中,其临时对象都不是最终须要的,能够说是没必要要分配的。ui

这样就产生了对StringBuilder类型的需求。StringBuilder类型的设计思想源于构造器的设计模式。构造器设计模式致力于解决复杂对象的构造问题,而对于字符串对象,正须要这样的构造器来进行组装。StringBuilder类型在最终产生String对象以前,将不产生任何String对象,这很好的解决了字符串的性能问题。一旦StringBuilder的ToSting方法被调用后,最终的字符串就被产生,而随后的操做将致使一个新的字符串对象的分配。编码

对于非托管的代码,字符串的操做是直接基于内存的,若是使用字符串类型和非托管资源进行操做,那潜在地违反了字符串对象不可变的原则。全部StringBuilder经常别用来和非托管代码进行交互。加密


3 如何在String和Byte[]对象之间进行转换

   比特

比特(bit)是指一个位。

  字节

字节(byte)在C#中由8个比特来构成。它的值能够由一个0~255的整数表示,可是C#中不容许隐式地把一个整数变量赋值给一个字节变量,下面的代码将编译错误:

int i = 10;
byte b = i;

  编码

编码能够说是数字信息和现实信息的转换机制。一种编码经常就定义一种字符集合转换的原则,经常使用的编码方式包括UTF八、GB23十二、Unicode 等。

 

字符串和字节数组的转换依赖于编码方式的使用,不一样的编码准则使用不一样的算法进行。System.Text.Encoding类型提供了大部分常见的编码算法支持,用以进行字符串和字节数组直接的转换。

示例代码:

    class StringByte
    {
        static void Main(string[] args)
        {
            String s = "我是字符串,I am string";

            //字节数组转换到字符串
            Byte[] utf8 = StringToByte(s, 
                Encoding.UTF8);
            Byte[] gb2312 = StringToByte(s, 
                Encoding.GetEncoding("GB2312"));
            Byte[] unicode = StringToByte(s, 
                Encoding.Unicode);
            Console.WriteLine(utf8.Length);
            Console.WriteLine(gb2312.Length);
            Console.WriteLine(unicode.Length);

            //转换回字符串
            Console.WriteLine(ByteToString(utf8, 
                Encoding.UTF8));
            Console.WriteLine(ByteToString(gb2312, 
                Encoding.GetEncoding("GB2312")));
            Console.WriteLine(ByteToString(unicode,
                Encoding.Unicode));
            Console.Read();
        }
        static Byte[] StringToByte(String s, Encoding encoding)
        {
            return encoding.GetBytes(s);
        }
        static String ByteToString(Byte[] b, Encoding encoding)
        {
            return encoding.GetString(b);
        }
    }

输出:

27
22
34
我是字符串,I am string
我是字符串,I am string
我是字符串,I am string


4 简述BASE64编码的做用以及C#中对其的支持

 BASE64编码是一种用于混淆明码的编程方式,其算法是把原来8位字节数组顺序分配到新的6位字节数组中,再在每一个字节的高2位填充0来组成新的8位字节数组。在.NET中Covert类型能够用来进行BASE64字符串和8位字节数组之间的转换。

        static void Main(string[] args)
        {
            String abc = "abcde";
            //生成UTF8字节数组
            Byte[] bytes = Encoding.UTF8.GetBytes(abc);
            //转换成Base64字符串
            String base64 = BytesToBase64(bytes);
            Console.WriteLine(base64);
            //转换回UTF8字节数组
            bytes = Base64ToBytes(base64);
            //转换回字符串
            Console.WriteLine(Encoding.UTF8.GetString(bytes));
            Console.Read();
        }
        //把8位字节数组转换成Base64字符串
        static String BytesToBase64(Byte[] bytes)
        {
            try
            {
                return Convert.ToBase64String(bytes);
            }
            catch
            {
                return null;
            }
        }
        //把Base64字符串转换成8位字节数组
        static Byte[] Base64ToBytes(String base64)
        {
            try
            {
                return Convert.FromBase64String(base64);
            }
            catch
            {
                return null;
            }
        }

输出:

YWJjZGU=
abcde


5 SecureString的实例如何被分配和释放

 System.SecureString 提供了加密的字符串类型。其对象会被分配在非托管堆中,并以加密的形式保存。对于SecureString的操做都是逐字符的,SecureString会负责在操做时进行加密和解密。SecureString实现了标准的Dispose/Finalize方法,对象被释放是先被所有布置为0,以保证机密信息不会在内存中驻留过长时间。

       static void Main(string[] args)
        {
            //使用using保证Dispose方法被调用
            using (SecureString ss = new SecureString())
            {  //只能逐字符地访问SecureString对象
                ss.AppendChar('a');
                ss.AppendChar('c');
                ss.AppendChar('d');
                ss.InsertAt(1, 'c');
                PrintSecurityString(ss);
                Console.Read();
            }
        }

        public unsafe static void PrintSecurityString(SecureString ss)
        {
            char* buffer = null;
            try
            {  //只能逐字符地访问SecureString对象
                buffer = (char*)Marshal.SecureStringToCoTaskMemUnicode(ss);
                for (int i = 0; *(buffer + i) != '\0'; i++)
                    Console.Write(*(buffer + i));
                Console.Write("\r\n");
            }
            finally
            {  //释放内存
                if (buffer != null)
                    Marshal.ZeroFreeCoTaskMemUnicode((System.IntPtr)buffer);
            }
        }

 

为了显示SecureString的内容,程序要访问非托管资源内存块,PrintSecurityString使用了unsafe关键字,因此编译时须要添加/unsafe 开发。

若是出现编译错误:不安全代码只会在使用 /unsafe 编译的状况下出现。只须要把程序属性中的“生成”标签下的“容许不安全代码”勾上就行了。

运行输出:

accd


6 什么是字符串池机制

字符串池机制致力于改善程序的性能。CLR会保留程序中出现过的字符串对象的集合,而且在须要新的字符串时,先检查已有的集合,在检查成功时返回已有对象的引用。若是不存在,则新分配一个字符串对象,同时把其添加到内部容器中。可是当程序用new关键字明显地申明新分配一个字符串对象时,该机制不会起做用。字符串池机制能够经过程序集元数据特性进行控制,C#默认是打开字符串池机制的。

        static void Main(string[] args)
        { 
            //两个字符串对象,理论上引用应该不相等
            //但因为字符串池的机制,二者实际指向了同一对象
            String a = "abcde";
            String b = "abcde";
            Console.WriteLine(Object.ReferenceEquals(a, b));

            //在本书前面章节的例子已中有介绍,编译器会优化这样的代码
            //因此这行代码等同于String c="abcde";
            //因为字符串池,c和a仍是指向同一对象
            String c = "a" + "b" + "c" + "d" + "e";
            Console.WriteLine(Object.ReferenceEquals(a, c));

            //显式使用new来分配内存
            //这时候字符串池机制不能起做用,d和a指向不一样对象
            Char[] chars ={ 'a', 'b', 'c', 'd', 'e' };
            String d = new String(chars);
            Console.WriteLine(Object.ReferenceEquals(a, d));

            Console.Read();
        }

 

输出:

True
True
False

转载请注明出处:

做者:JesseLZJ
出处:http://jesselzj.cnblogs.com

相关文章
相关标签/搜索