文章出處

今天寫了一個簡單的.NET Core RC2控制臺程序,發現中文顯示一直是亂碼。查看操作系統設置,沒有問題;查看源文件編碼,也沒有問題;甚至查看了Console字符編碼相關的注冊表,依然沒有發現問題。難道NET Core到了RC2,莫非連一些常用的編碼都不支持嗎?

現在給大家重現這個問題,通過VS 2015創建一個.NET Core控制臺程序。

image

我們在Main方法中只編寫了如下幾行行程序,將輸入的字符串直接打印出來。

   1: using System;
   2:  
   3: namespace App
   4: {
   5:     public class Program
   6:     {
   7:         public static void Main(string[] args)
   8:         {
   9:             while (true)
  10:             {
  11:                 Console.WriteLine(Console.ReadLine());
  12:             }
  13:         }
  14:     }
  15: }

運行程序并分別輸入中文和英文,我們會發現輸入的中文顯示為亂碼。

image

為了進一步證明.NET Core對編碼的局限,我們按照如下的方式調用Encoding的GetEncoding方法分別獲取兩種中文編碼:GB2312和CP936。

   1: using System;
   2: using System.Text;
   3:  
   4: namespace App
   5: {
   6:     public class Program
   7:     {
   8:         public static void Main(string[] args)
   9:         {
  10:             try
  11:             {
  12:                 Console.WriteLine(Encoding.GetEncoding(936));
  13:             }
  14:             catch (Exception ex)
  15:             {
  16:                 Console.WriteLine(ex.Message);
  17:             }
  18:  
  19:             try
  20:             {
  21:                 Console.WriteLine(Encoding.GetEncoding("GB2312"));
  22:             }
  23:             catch (Exception ex)
  24:             {
  25:                 Console.WriteLine(ex.Message);
  26:             }
  27:         }
  28:     }
  29: }

程序執行結果證明,上述兩種中文編碼均不支持。

image

我們提供的兩種中文編碼在默認情況下都不支持,是因為默然情況下它們的EncodingProvider沒有注冊。上面顯示的錯誤消息其實也提到了這一點,并且提到一個用于注冊EncodingProvider的方法(Encoding.RegisterProvider)。于是我們按照下面的方式注冊一個CodePagesEncodingProvider。

   1: using System;
   2: using System.Text;
   3:  
   4: namespace App
   5: {
   6:     public class Program
   7:     {
   8:         public static void Main(string[] args)
   9:         {
  10:             Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
  11:             Console.WriteLine(Encoding.GetEncoding(936));
  12:             Console.WriteLine(Encoding.GetEncoding("GB2312"));
  13:             while (true)
  14:             {
  15:                 Console.WriteLine(Console.ReadLine());
  16:             }
  17:         }
  18:     }
  19: }

CodePagesEncodingProvider定義在NuGet包“System.Text.Encoding.CodePages”之中,所以我們需要現在Project.json文件中按照如下的方式注冊對應的依賴。

   1: {
   2:   ...
   3:   "dependencies": {
   4:     "Microsoft.NETCore.App": {
   5:       "type": "platform",
   6:       "version": "1.0.0-rc2-3002702"
   7:     },
   8:     "System.Text.Encoding.CodePages":  "4.0.1-rc2-24027"
   9:   },
  10:   ...
  11: }

再次執行我們的程序后一切正常。

image

這個小問題其實體現了.NET Core最大的一個設計原則,那就是真正的模塊化。對于.NET Framework來說,基礎類型和API基本上通過幾個核心的程序集來承載(比如mscorlib.dll,System.dll、System.Core.dll等),也就是在部署的時候,這些個程序集都是必需的——可能我們只使用到其中很少的API。這樣的設計對于桌面應用,沒有什么問題,現在.NET Core要實現真正的跨平臺,并且創建適合多種設備的統一應用(UWP),這樣的部署方式就有問題了。所有.NET Core將很多“不那么核心”的API分離出來定義在其他的程序集中,并通過相應的NuGet包來承載。那么我們的應用就可以“按需使用”這些NuGet包了。這是一種“pay-for-play”設計。


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()