.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

相關文章
相關標籤/搜索