一直沒有深刻的學習字符集和編碼的知識(如今也沒有深刻),今天查閱了一些資料,弄明白了一些事情,本文就簡單記錄一下。html
字符集是指一些符號組成的集合,編碼是對指定字符集如何表示爲字節的一種規則,一個字符集能夠由多種編碼。算法
參考文章:http://www.cnblogs.com/skynet/archive/2011/05/03/2035105.html。編程
測試程序數組
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 }
輸出結果app
注:系統的默認編碼和操做系統的語言環境有關係,我是中文操做系統,因此這裏的輸出是:GB2312。學習
這個問題和源代碼所在的文件的編碼沒有任何關係,文件的格式只是影響開發期間的編程工做,如:採用ASCII編碼的文件不能使用中文變量名。測試
由於Char的內部表示和Short是同樣的,因此不難想象.NET使用的是Unicode的16位編碼,讓咱們測試一下。編碼
測試程序spa
1 public static void 語言的字符串採用的編碼() 2 { 3 Console.WriteLine("\n***" + 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("\n***" + 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("\n***" + 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是採用ASCII編碼,早上經羣裏的朋友斧正,原來是根據不一樣的環境會採用不一樣的編碼,中文操做系統多少是GB2312。
測試程序
1 public static void 讀取包含了ANSI字符的ANSI編碼文件() 2 { 3 Console.WriteLine("\n***" + System.Reflection.MethodInfo.GetCurrentMethod().Name + "***"); 4 5 var file = @"E:\Coding\HappyStudy\EncodingStudy\EncodingStudy\ANSI.txt"; 6 Console.WriteLine("使用GB2312編碼讀取的內容:" + File.ReadAllText(file, Encoding.GetEncoding("GB2312"))); 7 }
程序中的字符串使用是採用Unicode進行編碼的,咱們指的編碼轉換多少是指不一樣的IO流之間的轉換,簡單的思路是:
注:應該有快捷的算法在字節級別直接在兩種編碼規則之間作映射的,這裏沒有深究。
爲何.NET沒有提供自動識別文件編碼的功能?估計是無法支持,現實確實是無法支持,具體來講是隻能支持個別編碼的自動識別,原理參考這篇文章:http://blog.csdn.net/lipeijs3/article/details/5062243。
.NET中處理編碼仍是比較舒服的,改天得看看動態語言是如何處理的,等幾天寫一篇Ruby相關的編碼文章。