解析StreamReader與文件亂碼問(wèn)題的解決方法
相信很多人在讀取文件的時(shí)候都會(huì)碰到亂碼的情況,所謂亂碼就是錯(cuò)亂的編碼的意思,造成亂碼的是由于編碼不一致導(dǎo)致的。
演示程序:
新建3個(gè)文本文件:

編碼和名字一樣,分別是ansi,Unicode,utf8
里面的內(nèi)容都是:
~!@#¥%……&*()
abcdefg
123456789
測(cè)試數(shù)據(jù)



讀取這些文件的代碼如下:
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("************************************************************");
}
}
}
輸出入下:

由于第一個(gè)文件使用ansi編碼,但是StreamReader 的默認(rèn)構(gòu)造函數(shù)使用的是utf8編碼,所以亂碼了。
StreamReader 旨在以一種特定的編碼輸入字符,而 Stream 類(lèi)用于字節(jié)的輸入和輸出。 使用 StreamReader 讀取標(biāo)準(zhǔn)文本文件的各行信息。
除非另外指定, StreamReader 的默認(rèn)編碼為 UTF-8,而不是當(dāng)前系統(tǒng)的 ANSI 代碼頁(yè)。 UTF-8 可以正確處理 Unicode 字符并在操作系統(tǒng)的本地化版本上提供一致的結(jié)果。
所以解決上面的編碼問(wèn)題的解決方案是使用StreamReader,并且傳遞Encoding.Default作為編碼,一般在中文操作系統(tǒng)中,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("************************************************************");
}
}
}
輸出如下:

從這里得到一個(gè)結(jié)論:使用StreamReader,并且使用Encoding.Default 作為編碼。
很可惜,上面的這個(gè)結(jié)論在某些情況下頁(yè)會(huì)存在問(wèn)題,例如在你的操作系統(tǒng)中Encoding.Default 是Encoding.UTF8的時(shí)候。
最完美的解決方案是:文件使用什么編碼保存的,就用什么編碼來(lái)讀取。
那如何得到文件的編碼呢?
使用下面的代碼就可以了:
public static Encoding GetEncoding(string filePath)
{
if (filePath == null)
{
throw new ArgumentNullException("filePath");
}
Encoding encoding1 = Encoding.Default;
if (File.Exists(filePath))
{
try
{
using (FileStream stream1 = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
if (stream1.Length > 0)
{
using (StreamReader reader1 = new StreamReader(stream1, true))
{
char[] chArray1 = new char[1];
reader1.Read(chArray1, 0, 1);
encoding1 = reader1.CurrentEncoding;
reader1.BaseStream.Position = 0;
if (encoding1 == Encoding.UTF8)
{
byte[] buffer1 = encoding1.GetPreamble();
if (stream1.Length >= buffer1.Length)
{
byte[] buffer2 = new byte[buffer1.Length];
stream1.Read(buffer2, 0, buffer2.Length);
for (int num1 = 0; num1 < buffer2.Length; num1++)
{
if (buffer2[num1] != buffer1[num1])
{
encoding1 = Encoding.Default;
break;
}
}
}
else
{
encoding1 = Encoding.Default;
}
}
}
}
}
}
catch (Exception exception1)
{
throw;
}
if (encoding1 == null)
{
encoding1 = Encoding.UTF8;
}
}
return encoding1;
}
這段代碼使用encoding1.GetPreamble()方法來(lái)得到編碼的字節(jié)序列,然后重新讀取數(shù)據(jù),比較數(shù)據(jù),如果不相同則說(shuō)明是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("當(dāng)前編碼:" + reader.CurrentEncoding.EncodingName);
Console.WriteLine("************************************************************");
}
}
}
輸出如下:

- File, FileReader 和 Ajax 文件上傳實(shí)例分析(php)
- 基于C#中XmlReader讀取Xml的深入分析
- c#中executereader執(zhí)行查詢(xún)示例分享
- javascript結(jié)合fileReader 實(shí)現(xiàn)上傳圖片
- Android 數(shù)據(jù)存儲(chǔ)之 FileInputStream 工具類(lèi)及FileInputStream類(lèi)的使用
- 解析Java的InputStream類(lèi)并借助其讀取ppt文件
- 談?wù)劵趇frame、FormData、FileReader三種無(wú)刷新上傳文件的方法
- InputStreamReader和BufferedReader用法及實(shí)例講解
- InputStreamReader 和FileReader的區(qū)別及InputStream和Reader的區(qū)別
相關(guān)文章
C#難點(diǎn)逐個(gè)擊破(8):可空類(lèi)型System.Nullable
null值用來(lái)表示數(shù)據(jù)類(lèi)型未被賦予任何值,它是一種引用類(lèi)型;void表示沒(méi)有類(lèi)型,或者說(shuō)是沒(méi)有任何值。null與void的區(qū)別可以認(rèn)為void是根本沒(méi)有,而null是一個(gè)空箱子,里面什么都沒(méi)有。2010-02-02
webBrowser執(zhí)行js的方法,并返回值,c#后臺(tái)取值的實(shí)現(xiàn)
下面小編就為大家?guī)?lái)一篇webBrowser執(zhí)行js的方法,并返回值,c#后臺(tái)取值的實(shí)現(xiàn)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-12-12
C#以太網(wǎng)Sockets客戶(hù)端設(shè)計(jì)實(shí)現(xiàn)
本文主要介紹了C#以太網(wǎng)Sockets客戶(hù)端設(shè)計(jì)實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-02-02
Unity3D實(shí)現(xiàn)物體旋轉(zhuǎn)縮放移動(dòng)效果
這篇文章主要為大家詳細(xì)介紹了Unity3D實(shí)現(xiàn)物體旋轉(zhuǎn)縮放移動(dòng)效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-02-02

