[VS2015] 就專案在VS2013之後開啟編碼問題


我這邊是自己先用Notepad++把檔案開起來轉碼到UTF8,不過有更好的辦法如下



潛盾機-解決VS2015程式檔BIG5相容問題

改用VS2015後沒多久就發現它處理BIG5(ANSI)編碼程式碼的原則不同於以往(推測與編譯器改用Roslyn有關),導致部分使用BIG5編碼存檔的古老程式檔,會因許功蓋造成編譯錯誤。
PO文隔兩天同事跟我說,他們換VS2015後也射了好一陣子茶包,最後爬文又爬回我的文章。XD 後來聊到可以寫程式把所有BIG5編碼程式檔轉成UTF8一勞永逸,同事說檔案沒幾個,手動另存就搞定了,還不需要養乳牛。
這兩天,收到網友留言詢問VS2015是否會修正這個問題;也有網友提到手上專案有成千上萬個cs,改了一個BIG5,還有千千萬萬個BIG5,只好跟VS2015說Goodbye。
首先,雖然不確定VS2015會不會針對此一Issue進行修正,但依我之見,BIG5編碼已經過時多年,除了在VS2015產生不相容,遇到中文難字及其他語系文字都得額外處理(在Visual Studio.NET 2003時代就有處理過)。因此,不管VS2015會不會修正,將程式碼統一改存UTF8編碼是正確的方向。
問題來了,如網友所說,若專案有上萬支cs,一一手動轉存UTF8的浩大工程確實令人心寒。我最愛打造這種可以省時省力的潛盾機,就寫支批次轉檔程式搞定吧!
這裡我假設專案的.cs檔案分成兩類,一部分已經是UTF8或Unicode編碼,其餘則為BIG5編碼(假設全部都是BIG5,排除摻雜簡體中文、日文等其他ANSI編碼的情況)。因此,可以用Directory.GetFiles()搜尋找出特定目錄(含子目錄)下的指定檔案型別(例如:cs及js),檢查檔案註記略過UTF8或Unicode編碼檔案,找到BIG5檔案後先用BIG5 Encoding讀取,再以UTF8 Encoding寫入就完成轉檔,而原來的檔案則加上.big5.bak副檔名備份保留。

專案編譯成Console Application,執行時提供路徑名稱作為參數,轉換程式就會掃瞄該目錄下所有的.cs及.js,一口氣將BIG5編碼程式碼轉存成UTF8。

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace B2UBatchConverter
{
    class Program
    {
        public class AnalyzeResult
        {
            public string Content;
            public Encoding Encoding;
        }

        //REF:http://goo.gl/jAJgIr by Rick Strahl
        public static AnalyzeResult AnalyzeFile(string srcFile)
        {
            //預設為Big5
            Encoding enc = Encoding.GetEncoding(950);

            //由前五碼識別出UTF8、Unicode、UTF32等編碼,其餘則視為
            byte[] buffer = new byte[5];
            using (FileStream file = new FileStream(srcFile, FileMode.Open))
            {
                file.Read(buffer, 0, 5);
                file.Close();

                if (buffer[0] == 0xef && buffer[1] == 0xbb && buffer[2] == 0xbf)
                    enc = Encoding.UTF8;
                else if (buffer[0] == 0xfe && buffer[1] == 0xff)
                    enc = Encoding.Unicode;
                else if (buffer[0] == 0 && buffer[1] == 0 && 
                         buffer[2] == 0xfe && buffer[3] == 0xff)
                    enc = Encoding.UTF32;
                else if (buffer[0] == 0x2b && buffer[1] == 0x2f && buffer[2] == 0x76)
                    enc = Encoding.UTF7;
            }
            //使用指定的Encoding讀取內容
            return new AnalyzeResult()
            {
                Content = File.ReadAllText(srcFile, enc),
                Encoding = enc
            };
        }

        static void Main(string[] args)
        {
            //args = new string[] { "D:\\Lab\\L805\\ConApp" };
            string path = args[0];
            //列舉要搜尋轉碼的副檔名
            var scanFileTypes = "cs,js".Split(',');
            //略過不處理的資料夾名稱
            var skipFolders = "bin,obj".Split(',');
            foreach (var file in
                //列舉所有子目錄下的檔案
                Directory.GetFiles(path, "*.*", SearchOption.AllDirectories))
            {
                //取得副檔名
                var ext = Path.GetExtension(file).TrimStart('.').ToLower();
                //若非預先指定的副檔名就略過不處理
                if (!scanFileTypes.Contains(ext)) continue;
                //處於\bin\* \obj\*目錄下的檔案也一律略過
                if (skipFolders.Any(o => file.Contains(
                    Path.DirectorySeparatorChar + o + Path.DirectorySeparatorChar))) 
                    continue;

                //讀取檔案內容並識別編碼
                var analysis = AnalyzeFile(file);
                if (analysis.Encoding.CodePage == 950) //BIG5編號檔案才要處理
                {
                    Console.Write("Process File {0}...", file);
                    //將原檔更名為*.big5.bak
                    var bakFile = file + ".big5.bak";
                    if (File.Exists(bakFile)) File.Delete(bakFile);
                    File.Move(file, bakFile);
                    //重新以UTF8寫入
                    File.WriteAllText(file, analysis.Content, Encoding.UTF8);
                    Console.WriteLine(" done!");
                }
                else
                {
                    Console.WriteLine("Skip File {0} / {1}", file, 
                        analysis.Encoding.EncodingName);
                }
            }
        }
    }

}

執行範例如下,原本BIG5編碼的B5Class.cs另存成B5Class.cs.big5.bak,而B5Class.cs已改為UTF8編碼,就算有成千上萬支程式要轉碼也不怕。
希望這個工具能解決一些朋友的困擾。

【提醒】批次轉換前請務必先備份,以避免轉換出錯造成資料遺失。

轉自 : 
http://blog.darkthread.net/post-2015-08-07-big5-utf8-source-code-batch-converter.aspx

留言

熱門文章