.NET:字符集和編碼學習總結

背景

一直沒有深刻的學習字符集和編碼的知識(如今也沒有深刻),今天查閱了一些資料,弄明白了一些事情,本文就簡單記錄一下。html

字符集和編碼

字符集是指一些符號組成的集合,編碼是對指定字符集如何表示爲字節的一種規則,一個字符集能夠由多種編碼。算法

參考文章: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         }

輸出結果app

注:系統的默認編碼和操做系統的語言環境有關係,我是中文操做系統,因此這裏的輸出是:GB2312。學習

.NET中使用何種編碼表示字符串?

這個問題和源代碼所在的文件的編碼沒有任何關係,文件的格式只是影響開發期間的編程工做,如:採用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在中文操做系統下原來是GB2212

昨晚覺得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流之間的轉換,簡單的思路是:

  1. 將「源流」轉換爲.NET字符串(Unicode)編碼。
  2. 將.NET字符串以目標編碼寫入「目標流」。

注:應該有快捷的算法在字節級別直接在兩種編碼規則之間作映射的,這裏沒有深究。

能自動識別文件編碼嗎?

爲何.NET沒有提供自動識別文件編碼的功能?估計是無法支持,現實確實是無法支持,具體來講是隻能支持個別編碼的自動識別,原理參考這篇文章:http://blog.csdn.net/lipeijs3/article/details/5062243

備註

.NET中處理編碼仍是比較舒服的,改天得看看動態語言是如何處理的,等幾天寫一篇Ruby相關的編碼文章。

相關文章
相關標籤/搜索