相信很多人在讀取文件的時候都會碰到亂碼的情況,所謂亂碼就是錯亂的編碼的意思,造成亂碼的是由於編碼不一致導致的。
演示程序:
新建3個文本文件:
編碼和名字一樣,分別是ansi,Unicode,utf8
里面的內容都是:
~!@#¥%……&*()
abcdefg
123456789
測試數據
讀取這些文件的代碼如下:
public static void Main()
{
List<string> lstFilePath = new List<string>()
{
"H:\\TestText\\ansi.txt",
"H:\\TestText\\unicode.txt",
"H:\\TestText\\utf8.txt"
};
foreach (string filePath in lstFilePath)
{
using (StreamReader reader = new StreamReader(filePath))
{
Console.WriteLine("讀取文件" + filePath);
Console.WriteLine(reader.ReadToEnd());
Console.WriteLine("************************************************************");
}
}
}
輸出入下:
由於第一個文件使用ansi編碼,但是StreamReader 的默認構造函數使用的是utf8編碼,所以亂碼了。
StreamReader 旨在以一種特定的編碼輸入字符,而 Stream 類用於字節的輸入和輸出。 使用 StreamReader 讀取標准文本文件的各行信息。
除非另外指定, StreamReader 的默認編碼為 UTF-8,而不是當前系統的 ANSI 代碼頁。 UTF-8 可以正確處理 Unicode 字符並在操作系統的本地化版本上提供一致的結果。
所以解決上面的編碼問題的解決方案是使用StreamReader,並且傳遞Encoding.Default作為編碼,一般在中文操作系統中,Encoding.Default是Gb2312編碼。
public static void Main()
{
List<string> lstFilePath = new List<string>()
{
"H:\\TestText\\ansi.txt",
"H:\\TestText\\unicode.txt",
"H:\\TestText\\utf8.txt"
};
foreach (string filePath in lstFilePath)
{
using (StreamReader reader = new StreamReader(filePath,Encoding.Default))
{
Console.WriteLine("讀取文件" + filePath);
Console.WriteLine(reader.ReadToEnd());
Console.WriteLine("************************************************************");
}
}
}
輸出如下:
從這里得到一個結論:使用StreamReader,並且使用Encoding.Default 作為編碼。
很可惜,上面的這個結論在某些情況下頁會存在問題,例如在你的操作系統中Encoding.Default 是Encoding.UTF8的時候。
最完美的解決方案是:文件使用什么編碼保存的,就用什么編碼來讀取。
那如何得到文件的編碼呢?
使用下面的代碼就可以了:
GetEncoding
這段代碼使用encoding1.GetPreamble()方法來得到編碼的字節序列,然后重新讀取數據,比較數據,如果不相同則說明是Encoding.Default.
否則是Encoding.Utf8.
有了GetEncoding(filename)方法后,可以將上面的讀取代碼修改如下:
public static void Main()
{
List<string> lstFilePath = new List<string>()
{
"H:\\TestText\\ansi.txt",
"H:\\TestText\\unicode.txt",
"H:\\TestText\\utf8.txt"
};
foreach (string filePath in lstFilePath)
{
using (StreamReader reader = new StreamReader(filePath, GetEncoding(filePath)))
{
Console.WriteLine("讀取文件" + filePath);
Console.WriteLine(reader.ReadToEnd());
Console.WriteLine("當前編碼:" + reader.CurrentEncoding.EncodingName);
Console.WriteLine("************************************************************");
}
}
}
輸出如下:







