C#自動識別文件編碼

在作導入微信商戶後臺退款數據時,不管怎麼設置編碼導出來都是亂碼,後來在網上找了這個識別文件編碼的代碼,感受不錯。微信

最後識別出來是gb2312,看來我仍是太渣了,只能吃土了,居然忘記了這個編碼。函數

 

下面,上代碼。編碼

  1 /// <summary>   
  2     /// 用於取得一個文本文件的編碼方式(Encoding)。   
  3     /// </summary>   
  4     public class TxtFileEncoder
  5     {
  6         public TxtFileEncoder()
  7         {
  8             //   
  9             // TODO: 在此處添加構造函數邏輯   
 10             //   
 11         }
 12         /// <summary>   
 13         /// 取得一個文本文件的編碼方式。若是沒法在文件頭部找到有效的前導符,Encoding.Default將被返回。   
 14         /// </summary>   
 15         /// <param name="fileName">文件名。</param>   
 16         /// <returns></returns>   
 17         public static Encoding GetEncoding(string fileName)
 18         {
 19             return GetEncoding(fileName, Encoding.Default);
 20         }
 21         /// <summary>   
 22         /// 取得一個文本文件流的編碼方式。   
 23         /// </summary>   
 24         /// <param name="stream">文本文件流。</param>   
 25         /// <returns></returns>   
 26         public static Encoding GetEncoding(FileStream stream)
 27         {
 28             return GetEncoding(stream, Encoding.Default);
 29         }
 30         /// <summary>   
 31         /// 取得一個文本文件的編碼方式。   
 32         /// </summary>   
 33         /// <param name="fileName">文件名。</param>   
 34         /// <param name="defaultEncoding">默認編碼方式。當該方法沒法從文件的頭部取得有效的前導符時,將返回該編碼方式。</param>   
 35         /// <returns></returns>   
 36         public static Encoding GetEncoding(string fileName, Encoding defaultEncoding)
 37         {
 38             FileStream fs = new FileStream(fileName, FileMode.Open);
 39             Encoding targetEncoding = GetEncoding(fs, defaultEncoding);
 40             fs.Close();
 41             return targetEncoding;
 42         }
 43         /// <summary>   
 44         /// 取得一個文本文件流的編碼方式。   
 45         /// </summary>   
 46         /// <param name="stream">文本文件流。</param>   
 47         /// <param name="defaultEncoding">默認編碼方式。當該方法沒法從文件的頭部取得有效的前導符時,將返回該編碼方式。</param>   
 48         /// <returns></returns>   
 49         public static Encoding GetEncoding(FileStream stream, Encoding defaultEncoding)
 50         {
 51             Encoding targetEncoding = defaultEncoding;
 52             if (stream != null && stream.Length >= 2)
 53             {
 54                 //保存文件流的前4個字節   
 55                 byte byte1 = 0;
 56                 byte byte2 = 0;
 57                 byte byte3 = 0;
 58                 byte byte4 = 0;
 59                 //保存當前Seek位置   
 60                 long origPos = stream.Seek(0, SeekOrigin.Begin);
 61                 stream.Seek(0, SeekOrigin.Begin);
 62 
 63                 int nByte = stream.ReadByte();
 64                 byte1 = Convert.ToByte(nByte);
 65                 byte2 = Convert.ToByte(stream.ReadByte());
 66                 if (stream.Length >= 3)
 67                 {
 68                     byte3 = Convert.ToByte(stream.ReadByte());
 69                 }
 70                 if (stream.Length >= 4)
 71                 {
 72                     byte4 = Convert.ToByte(stream.ReadByte());
 73                 }
 74                 //根據文件流的前4個字節判斷Encoding   
 75                 //Unicode {0xFF, 0xFE};   
 76                 //BE-Unicode {0xFE, 0xFF};   
 77                 //UTF8 = {0xEF, 0xBB, 0xBF};   
 78                 if (byte1 == 0xFE && byte2 == 0xFF)//UnicodeBe   
 79                 {
 80                     targetEncoding = Encoding.BigEndianUnicode;
 81                 }
 82                 if (byte1 == 0xFF && byte2 == 0xFE && byte3 != 0xFF)//Unicode   
 83                 {
 84                     targetEncoding = Encoding.Unicode;
 85                 }
 86                 if (byte1 == 0xEF && byte2 == 0xBB && byte3 == 0xBF)//UTF8   
 87                 {
 88                     targetEncoding = Encoding.UTF8;
 89                 }
 90                 //恢復Seek位置         
 91                 stream.Seek(origPos, SeekOrigin.Begin);
 92             }
 93             return targetEncoding;
 94         }
 95 
 96 
 97 
 98         // 新增長一個方法,解決了不帶BOM的 UTF8 編碼問題   
 99 
100         /// <summary>   
101         /// 經過給定的文件流,判斷文件的編碼類型   
102         /// </summary>   
103         /// <param name="fs">文件流</param>   
104         /// <returns>文件的編碼類型</returns>   
105         public static System.Text.Encoding GetEncoding(Stream fs)
106         {
107             byte[] Unicode = new byte[] { 0xFF, 0xFE, 0x41 };
108             byte[] UnicodeBIG = new byte[] { 0xFE, 0xFF, 0x00 };
109             byte[] UTF8 = new byte[] { 0xEF, 0xBB, 0xBF }; //帶BOM   
110             Encoding reVal = Encoding.Default;
111 
112             BinaryReader r = new BinaryReader(fs, System.Text.Encoding.Default);
113             byte[] ss = r.ReadBytes(4);
114             if (ss[0] == 0xFE && ss[1] == 0xFF && ss[2] == 0x00)
115             {
116                 reVal = Encoding.BigEndianUnicode;
117             }
118             else if (ss[0] == 0xFF && ss[1] == 0xFE && ss[2] == 0x41)
119             {
120                 reVal = Encoding.Unicode;
121             }
122             else
123             {
124                 if (ss[0] == 0xEF && ss[1] == 0xBB && ss[2] == 0xBF)
125                 {
126                     reVal = Encoding.UTF8;
127                 }
128                 else
129                 {
130                     int i;
131                     int.TryParse(fs.Length.ToString(), out i);
132                     ss = r.ReadBytes(i);
133 
134                     if (IsUTF8Bytes(ss))
135                         reVal = Encoding.UTF8;
136                 }
137             }
138             r.Close();
139             return reVal;
140 
141         }
142 
143         /// <summary>   
144         /// 判斷是不是不帶 BOM 的 UTF8 格式   
145         /// </summary>   
146         /// <param name="data"></param>   
147         /// <returns></returns>   
148         private static bool IsUTF8Bytes(byte[] data)
149         {
150             int charByteCounter = 1;  //計算當前正分析的字符應還有的字節數   
151             byte curByte; //當前分析的字節.   
152             for (int i = 0; i < data.Length; i++)
153             {
154                 curByte = data[i];
155                 if (charByteCounter == 1)
156                 {
157                     if (curByte >= 0x80)
158                     {
159                         //判斷當前   
160                         while (((curByte <<= 1) & 0x80) != 0)
161                         {
162                             charByteCounter++;
163                         }
164                         //標記位首位若爲非0 則至少以2個1開始 如:110XXXXX...........1111110X    
165                         if (charByteCounter == 1 || charByteCounter > 6)
166                         {
167                             return false;
168                         }
169                     }
170                 }
171                 else
172                 {
173                     //如果UTF-8 此時第一位必須爲1   
174                     if ((curByte & 0xC0) != 0x80)
175                     {
176                         return false;
177                     }
178                     charByteCounter--;
179                 }
180             }
181             if (charByteCounter > 1)
182             {
183                 throw new Exception("非預期的byte格式!");
184             }
185             return true;
186         }
187     }
相關文章
相關標籤/搜索