c# 讀txt出現亂碼的處理方式


用System.IO.StreamReader讀取包含漢字的txt文件時,經常會讀出亂碼(StreamWriater寫文本文件也有類似的問題),原因很簡單,就是文件的編碼(encoding)和StreamReader/Writer的encoding不對應。為了解決這個問題,我寫了一個類,來取得一個文本文件的encoding,這樣我們就可以創建對應的StreamReader和StreamWrite來讀寫,保證不會出現亂碼現象。其實原理很簡單,文本編輯器(比如XP自帶的記事本)在生成文本文件時,如果編碼格式和系統默認的編碼(中文系統下默認為GB2312)不一致時,會在txt文件開頭部分添加特定的“編碼字節序標識(Encoding Bit Order Madk,簡寫為BOM)”,類似PE格式的"MZ"文件頭。這樣它在讀取時就可以根據這個BOM來確定該文本文件生成時所使用的Encoding。這個BOM我們用記事本等程序打開默認是看不到的,但是用stream按字節讀取時是可以讀到的。我的這個TxtFileEncoding類就是根據這個BOM“文件頭”來確定txt文件生成時用到的編碼的。
 1 /// <summary>
 2     /// 獲取文本文件的編碼方式
 3     /// </summary>
 4     class TxtFileEncoding
 5     {
 6         public TxtFileEncoding(){}
 7 
 8         /// <summary>
 9         /// 獲取文本文件的編碼方式
10         /// </summary>
11         /// <param name="fileName"> 文件名 例如:path = @"D:\test.txt"</param>
12         /// <returns>返回編碼方式</returns>
13         public static Encoding GetEncoding(string fileName )
14         {
15             return GetEncoding(fileName, Encoding.Default);
16         }
17 
18         /// <summary>
19         /// 獲取文本流的編碼方式
20         /// </summary>
21         /// <param name="fs">文本流</param>
22         /// <returns>返回系統默認的編碼方式</returns>
23         public static Encoding GetEncoding(FileStream fs)
24         {
25             //Encoding.Default 系統默認的編碼方式
26             return GetEncoding(fs, Encoding.Default);
27         }
28 
29         /// <summary>
30         /// 獲取一個文本流的編碼方式
31         /// </summary>
32         /// <param name="fileName">文件名</param>
33         /// <param name="defaultEncoding">默認編碼方式。當該方法無法從文件的頭部取得有效的前導符時,將返回該編碼方式。</param>
34         /// <returns></returns>
35         public static Encoding GetEncoding(string fileName, Encoding defaultEncoding)
36         {
37             FileStream fs = File.Open(fileName,FileMode.Open);
38             Encoding targetEncoding = GetEncoding(fs, defaultEncoding);
39             fs.Close();
40             return targetEncoding;
41         }
42 
43         /// <summary>
44         /// 獲取一個文本流的編碼方式
45         /// </summary>
46         /// <param name="fs">文本流</param>
47         /// <param name="defaultEncoding">默認編碼方式。當該方法無法從文件的頭部取得有效的前導符時,將返回該編碼方式。</param>
48         /// <returns></returns>
49         public static Encoding GetEncoding(FileStream fs, Encoding defaultEncoding)
50         {
51             Encoding targetEncoding = defaultEncoding;
52             if (fs != null && fs.Length >= 2)
53             {
54                 byte b1 = 0;
55                 byte b2 = 0;
56                 byte b3 = 0;
57                 byte b4 = 0;
58 
59                 long oriPos = fs.Seek(0, SeekOrigin.Begin);
60                 fs.Seek(0, SeekOrigin.Begin);
61 
62                 b1 = Convert.ToByte(fs.ReadByte());
63                 b2 = Convert.ToByte(fs.ReadByte());
64                 if (fs.Length > 2)
65                 {
66                     b3 = Convert.ToByte(fs.ReadByte());
67                 }
68                 if (fs.Length > 3)
69                 {
70                     b4 = Convert.ToByte(fs.ReadByte());
71                 }
72 
73                 //根據文件流的前4個字節判斷Encoding
74                 //Unicode {0xFF, 0xFE};
75                 //BE-Unicode {0xFE, 0xFF};
76                 //UTF8 = {0xEF, 0xBB, 0xBF};
77                 if (b1 == 0xFE && b2 == 0xFF)//UnicodeBe
78                 {
79                     targetEncoding = Encoding.BigEndianUnicode;
80                 }
81                 if (b1 == 0xFF && b2 == 0xFE && b3 != 0xFF)//Unicode
82                 {
83                     targetEncoding = Encoding.Unicode;
84                 }
85                 if (b1 == 0xEF && b2 == 0xBB && b3 == 0xBF)//UTF8
86                 {
87                     targetEncoding = Encoding.UTF8;
88                 }
89 
90                 fs.Seek(0, SeekOrigin.Begin);
91             }
92             fs.Close();
93             return targetEncoding;
94         }
95     }

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM