難道.NET Core到R2連中文編碼都不支援嗎?
今天寫了一個簡單的.NET Core RC2控制檯程式,發現中文顯示一直是亂碼。檢視作業系統設定,沒有問題;檢視原始檔編碼,也沒有問題;甚至查看了Console字元編碼相關的登錄檔,依然沒有發現問題。難道NET Core到了RC2,莫非連一些常用的編碼都不支援嗎?
現在給大家重現這個問題,通過VS 2015建立一個.NET Core控制檯程式。
我們在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: }
執行程式並分別輸入中文和英文,我們會發現輸入的中文顯示為亂碼。
為了進一步證明.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: }
程式執行結果證明,上述兩種中文編碼均不支援。
我們提供的兩種中文編碼在預設情況下都不支援,是因為默然情況下它們的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: }
再次執行我們的程式後一切正常。
這個小問題其實體現了.NET Core最大的一個設計原則,那就是真正的模組化。對於.NET Framework來說,基礎型別和API基本上通過幾個核心的程式集來承載(比如mscorlib.dll,System.dll、System.Core.dll等),也就是在部署的時候,這些個程式集都是必需的——可能我們只使用到其中很少的API。這樣的設計對於桌面應用,沒有什麼問題,現在.NET Core要實現真正的跨平臺,並且建立適合多種裝置的統一應用(UWP),這樣的部署方式就有問題了。所有.NET Core將很多“不那麼核心”的API分離出來定義在其他的程式集中,並通過相應的NuGet包來承載。那麼我們的應用就可以“按需使用”這些NuGet包了。這是一種“pay-for-play”設計。