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 条评论
登录 后参与评论

相关文章

来自专栏跟着阿笨一起玩NET

C#实现文本文件合并

622
来自专栏JadePeng的技术博客

\x 开头编码的数据解码成中文

在python里,直接decode('utf-8')即可 >>> "\xE5\x85\x84\xE5\xBC\x9F\xE9\x9A\xBE\xE5\xBD\x...

81012
来自专栏柠檬先生

es6 Symbol

1.Symbol 值通过Symbol 函数生成,凡是属性名属于Symbol 类型,就是   独一无二的,可以保证不会与其他属性名冲突。       // 没有参...

1847
来自专栏枕边书

WEB开发中的字符集和编码

引言 我相信很多人在初接触编程时,都被字符集狠狠地虐过,特别是数据库的中文乱码问题,那么乱码是怎么产生的呢? 我们都知道计算机是以二进制存储和运行的,那么它是怎...

2015
来自专栏web前端教室

javascript 红皮高程(7)

javascript的数值表示,真是。。 这还有个NaN,非数值(Not a Number),就是不是数字。然后已是书里写着,是一个特殊的数值。 这让小学文化的...

1777
来自专栏GIS讲堂

js实现城市首字母导航

471
来自专栏jeremy的技术点滴

现代Web开发系列教程_04

3107
来自专栏程序员的SOD蜜

.net访问PostgreSQL数据库发生“找不到函数名”的问题追踪

    PostgreSQL是一个使用广泛的免费开源的数据库,与MySQL比较,它更适合复杂的企业计算任务,而MySQL在互联网领域应用更为广泛,究其原因,可能...

2747
来自专栏Golang语言社区

【Go 语言社区】浅析javascript的间隔调用和延时调用

用 setInterval方法可以以指定的间隔实现循环调用函数,直到clearInterval方法取消循环 用clearInterval方法取消循环时,必须将s...

2684
来自专栏peakxie

Json string值如何传递0x00-0xFF(5分钟理解Unicode,UTF8)

项目中,想通过Json传递0x00-0xFF字符串,自然想到Json的string值。

2287

扫码关注云+社区