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     }

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏技术之路

【转】Go Interface 源码剖析

源网址:http://legendtkl.com/2017/07/01/golang-interface-implement/

1702
来自专栏Ryan Miao

Java8学习(4)-Stream流

Stream和Collection的区别是什么 流和集合的区别是什么? 粗略地说, 集合和流之间的差异就在于什么时候进行计算。集合是一个内存中的数据结构,它包...

9837
来自专栏刘远的专栏

airflow—给DAG实例传递参数(4)

我们需要在创建dag实例时传递参数,每个任务都可以从任务实例中获取需要的参数。

2.3K8
来自专栏GreenLeaves

C# Encoding

之前做公司项目的时候,对于C#编码这块总是一知半解,所以打算通过这篇笔记对C#编码(Encoding)进行彻底的扫盲,关于编码和字符集的基础知识,请参考字符集和...

2757
来自专栏jessetalks

背后的故事之 - 快乐的Lambda表达式(二)

快乐的Lambda表达式   上一篇 背后的故事之 - 快乐的Lambda表达式(一)我们由浅入深的分析了一下Lambda表达式。知道了它和委托以及普通方法的区...

2784
来自专栏机器学习入门

LWC 58:724. Find Pivot Index

LWC 58:724. Find Pivot Index 传送门:724. Find Pivot Index Problem: Given an array ...

2028
来自专栏开发与安全

算法:静态查找表(Static Search Table)(顺序查找、二分查找、插值查找、斐波纳契查找)

查找表(Search table)是由同一类型的数据元素(或记录)构成的集合。关键字(key)是数据元素中某个数据项的值,又称为键值,用它可以表示一个数据元素,...

2455
来自专栏逍遥剑客的游戏开发

关于中文文本的截取

2657
来自专栏码匠的流水账

聊聊flink的SourceFunction

flink-streaming-java_2.11-1.6.2-sources.jar!/org/apache/flink/streaming/api/func...

2022
来自专栏java一日一条

UML类图五种关系与代码的对应关系

注意1: Water类的生命期,它是当Animal类的GrounUp方法被调用的时候,才被实例化。

2911

扫码关注云+社区

领取腾讯云代金券