.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("\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相關的編碼文章。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM