Quantcast
Channel: 黑暗執行緒
Viewing all articles
Browse latest Browse all 2311

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

$
0
0

改用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副檔名備份保留。


using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace B2UBatchConverter
{
class Program
    {
publicclass AnalyzeResult
        {
publicstring Content;
public Encoding Encoding;
        }
 
//REF:http://goo.gl/jAJgIr by Rick Strahl
publicstatic AnalyzeResult AnalyzeFile(string srcFile)
        {
//預設為Big5
            Encoding enc = Encoding.GetEncoding(950);
 
//由前五碼識別出UTF8、Unicode、UTF32等編碼,其餘則視為
byte[] buffer = newbyte[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;
elseif (buffer[0] == 0xfe && buffer[1] == 0xff)
                    enc = Encoding.Unicode;
elseif (buffer[0] == 0 && buffer[1] == 0 && 
                         buffer[2] == 0xfe && buffer[3] == 0xff)
                    enc = Encoding.UTF32;
elseif (buffer[0] == 0x2b && buffer[1] == 0x2f && buffer[2] == 0x76)
                    enc = Encoding.UTF7;
            }
//使用指定的Encoding讀取內容
returnnew AnalyzeResult()
            {
                Content = File.ReadAllText(srcFile, enc),
                Encoding = enc
            };
        }
 
staticvoid 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);
                }
            }
        }
    }
}

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

執行範例如下,原本BIG5編碼的B5Class.cs另存成B5Class.cs.big5.bak,而B5Class.cs已改為UTF8編碼,就算有成千上萬支程式要轉碼也不怕。

希望這個工具能解決一些朋友的困擾。

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

【2015-08-07 更新】 感謝網友黃文生、Norton Lin在FB專頁留這補充兩款現成軟體工具:ConvertZ以及UTFCast也可以做到批次編碼轉換。 另外,ChrisTorng 也分享可與TFS整合的批次轉檔,並提到靠 StreamReader 建構式之 detectEncodingFromByteOrderMarks 參數偵測Encoding的小技巧。
謝謝大家的回饋。


Viewing all articles
Browse latest Browse all 2311

Trending Articles