2018年1月11日 星期四

C# 自動判別 BIG5 或 UTF-8 字串

若使用 BIG-5 的檔案格式存放 UTF-8 字串,可能導致無法正常顯示中文字元,透過字元數和字串數交互比對可以了解編碼差異,取得判斷結果。


BIG-5, UTF-8 偵測方式


儘管可能 getFile().currentEncoding 對目前沒有效果,但還可是可以從 Byte 看出來是否是  UTF8 ,就用轉碼成 String 的方式解決。

BIG-5 要 2 個 Byte 就可以顯是正常的中文字, UTF-8 則要 3 個才可以顯示正常的中文字,但判別時,因為 2 Byte 和 3 Byte 的明顯區別要大一點,所以辨識時用 4 個 Byte 的 BIG-5 來找到是否為 BIG-5 字碼。

資料


基本上,超過一個字的中文檔案,必須使用這種方式解決,首先辨識時,要先移除中文以外的字元來辨識,本章節寫的程式碼,是預設檔案的一開頭就有中文字,這點請特別注意。

如果只有一個字的檔案,只要判斷是 2 Byte 還是 3 Byte ,就可以知道是否為 UTF-8 或 BIG-5,如果有兩個字以上的檔案,透過 2 個字組合來知道 Byte 是否正常。

明顯分出區別


透過程式碼來看:

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

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(autoEncodingRead(@"C:\tmp\300.txt")); //讀入隨便的檔案
            Console.ReadLine(); //等待
        }
        
        public static string autoEncodingRead(string filename)
        {
            string result;
            byte[] fileb = File.ReadAllBytes(filename);
            Encoding enc = Encoding.Default; //在中文電腦跑的是 BIG-5

            Encoding RealEncoding = Encoding.Default; //BIG-5, 最後真實的編碼,如果正常,那就維持  BIG-5 不變

            //Console.WriteLine(fileb[0]);
            using (System.IO.StreamReader reader = new System.IO.StreamReader(filename, enc, true))
            {
                result = reader.ReadToEnd(); //全部字讀出來
                byte[] r = enc.GetBytes(result); //把字串全部讀成 Byte
                byte[] b = new byte[] { r[0], r[1], r[2] }; //UTF-8 偵測 Buffer
                byte[] b1 = new byte[] { r[0], r[1], r[2], r[3] }; //BIG-5 偵測 Buffer

                Console.WriteLine(Encoding.UTF8.GetString(b).Length); //顯示長度是否為 3
                Console.WriteLine(Encoding.Default.GetString(b1).Length); //顯示長度是否為 2

                if (Encoding.UTF8.GetString(b).Length + Encoding.Default.GetString(b1).Length != 5) //直接判斷兩者加起來是否為 5,不是則轉換編碼
                {
                    RealEncoding = Encoding.UTF8;
                    //Console.WriteLine("UTF-8");
                }
                else
                {
                    //Console.WriteLine("BIG5");
                }
            }

            using (System.IO.StreamReader reader = new System.IO.StreamReader(filename, RealEncoding, true))
            {
                result = reader.ReadToEnd();
            }

            return result;
        }
    }
}


Reference:
https://tw.answers.yahoo.com/question/index?qid=20060522000012KK03390
https://stackoverflow.com/questions/16072709/converting-string-to-byte-array-in-c-sharp
https://www.chilkatsoft.com/p/p_320.asp
https://gist.github.com/TaoK/945127
https://msdn.microsoft.com/en-us/library/kdcak6ye%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396
https://stackoverflow.com/questions/12771357/read-text-file-with-multiple-mixed-more-than-one-encoding
https://stackoverflow.com/questions/11654562/how-convert-byte-array-to-string
https://stackoverflow.com/questions/27555766/how-do-i-retrieve-image-properly-using-parsefile

沒有留言:

張貼留言

© Mac Taylor, 歡迎自由轉貼。
Background Email Pattern by Toby Elliott
Since 2014