C# 網絡編程之webBrowser亂碼問題及解決知識
在使用PHP+MySQL編寫網頁時,曾近就因為顯示中文亂碼”口口口???”困擾我很長時間,沒想到在C#製作瀏覽器或獲取XML頁麵時也經常會遇到顯示中文亂碼的問題,可想而知怎樣解決編碼問題或統一編碼問題是非常嚴重的問題。下麵就講講我的一些理解及解決方法吧!
一.瀏覽器實現
前麵我已經介紹了使用webBrowser控件實現"最簡單的瀏覽器"基本代碼如下所示:
//命名空間 using System.Net; using System.IO; //點擊"瀏覽"按鈕 private void button1_Click(object sender, EventArgs e) { //輸入URL string url = textBox1.Text; var request = (HttpWebRequest)WebRequest.Create(url); //HTTP請求 var response = (HttpWebResponse)request.GetResponse(); //HTTP應答 //顯示webBrowser中 Stream stream = response.GetResponseStream(); //獲取應答流 StreamReader sr = new StreamReader(stream); //從字節流中讀取字符 string content = sr.ReadToEnd(); webBrowser1.DocumentText = content; }
該方法通過獲取相應URL的應答內容,通過賦值數據流,再從字節流中讀取內容賦值給webBrowser控件中實現最簡單的瀏覽器;但通過該方法常常會遇到現實中文字符亂碼問題,或者是顯示格式錯誤等問題.例如訪問google等.
PS:這裏有另外一種方法調用webBrowser的Navigate方法將指定位置的文檔加載到控件中,其中一種重載方法Navigate(string)將製定的統一資源定位符URL處的文檔加載到WebBrowser控件中替換上一個文檔,而且實現該方法不會出現亂碼問題、排版問題、缺少http報錯問題.其實我很想知道封裝的該函數是如何實現的.
private void button1_Click(object sender, EventArgs e) { webBrowser1.Navigate(textBox1.Text.Trim()); }
二.亂碼問題
通過獲取網頁的響應字符集string str = response.CharacterSet(隻讀屬性)可以發現,當字符集為utf-8時才能正常顯示,否則其他編碼方式都會出現中文亂碼;這裏最常出現的亂碼編碼方式為ISO-8859-1,big5,gbk,gb2312等;而utf-8通常能顯示中文.ISO-8859-1:又稱Latin-1或"西歐語言",是單字節編碼,自身不能顯示中文,配合gbk或utf-8顯示中文,通常以byte[]形式存儲,以ISO-8859-1格式解碼會是亂碼,通常采用gb2313解碼;
big5:通行於台灣、香港地區的一個繁體字編碼方案,俗稱”大五碼“.上麵訪問香港google就是big5出現的亂碼.
utf-8:是一種針對Unicode的可變長度字符編碼,又稱萬國碼.它可以用來表示Unicode標準中的任何字符,且其編碼中的第一個字節仍與ASCII兼容,逐漸成為電子郵件、網頁及其他存儲或傳送文字的應用中,優先采用的編碼.
gb2312:是中華人民共和國國家漢字信息交換用編碼,全稱"信息交換用漢字編碼字符集",基本集共收入漢字6763個和非漢字圖形字符682個.gbk亦漢字編碼標準.
出現編碼方式的根本原因是在解析時使用的字符編碼和網頁的編碼方式不同,所以采用的解決方法通常是:
1.首先利用HttpWebResponse.CharacterSet屬性獲取字符集;
2.在根據不同的字符集設置相應的Encoding來避免亂碼.
三.解決方法
其中最簡單的方法是先獲取其指定網頁的字符集,在根據它的字符集采用相應的編碼方式進行解碼讀取.我們采用下麵代碼獲取該URL的字符集為"ISO-8859-1"
string str = response.CharacterSet; MessageBox.Show(str);
在設置其對應的編碼方式,通過定義Encoding enc字符編碼方式,其方法GetEncoding("相應編碼方式")設置字符編碼,然後在StreamReader(stream,enc)中采用對應設置的編碼方式從字節流中讀取內容.
private void button1_Click(object sender, EventArgs e) { //獲取輸入的URL string url = textBox1.Text; var request = (HttpWebRequest)WebRequest.Create(url); //HTTP請求 var response = (HttpWebResponse)request.GetResponse(); //HTTP應答 //顯示響應字符集 string str = response.CharacterSet; MessageBox.Show(str); //設置ISO-8859-1字符編碼方式 Encoding enc; if (response.CharacterSet != "ISO-8859-1") { enc = Encoding.GetEncoding(response.CharacterSet); } else { enc = Encoding.GetEncoding("GBK"); } //顯示webBrowser中 Stream stream = response.GetResponseStream(); //獲取應答流 StreamReader sr = new StreamReader(stream,enc); //從字節流中讀取字符 string content = sr.ReadToEnd(); webBrowser1.DocumentText = content; }
顯示結果如下:其中CharacterSet采用ISO-8859-1編碼方式,但從網頁源代碼中發現它的charset=gb2312所以我設置的Encoding.GetEncoding("GBK或GB2312").能正確顯示中文漢字:

其實當獲取指定網頁字符集時,采用指定編碼方式對其進行解碼的核心代碼就是幾句:(同樣可設置webBrowser.DocumentStream)
Stream stream = response.GetResponseStream(); StreamReader sr = new StreamReader(stream, System.Text.Encoding.GetEncoding("gb2312")); string content = sr.ReadToEnd();
也可以采用獲取到的文章內容content通過byte[] utf8Bytes = System.Text.Encoding.Convert(iso_8859_1, utf_8, isoBytes);這樣的語句轉換為相應的內容顯示;經常能看到這樣的通過byte[]轉換ISO-8859-1的方法,但本人沒有嚐試過.個人認為在讀入時就采用相對應的編碼方式比較好.
由於webBrowser是簡單的瀏覽器,肯定不能使用每一個頁麵都去找相應的characterSet字符集,因此我們可以設置相應的函數,直接調用函數實現顯示內容:(代碼感謝一位博主,https://blog.csdn.net/lemonay/article/details/8865939)
private static string GetHTMLbyWebRequest(string url) { //獲取輸入的URL var request = (HttpWebRequest)WebRequest.Create(url); //HTTP請求 var response = (HttpWebResponse)request.GetResponse(); //HTTP應答 Encoding encoding = System.Text.Encoding.Default; //當前字符編碼方式 //響應狀態為OK if (response.StatusDescription.ToUpper()=="OK") //大寫 { //設置獲取鏈接中網頁的編碼格式 switch (response.CharacterSet.ToLower()) //小寫 { case "gbk": encoding = Encoding.GetEncoding("GBK"); break; case "gb2312": encoding = Encoding.GetEncoding("GB2312"); break; case "utf-8": encoding = Encoding.UTF8; break; case "iso-8859-1": encoding = Encoding.GetEncoding("GBK"); //GB2312 break; case "big5": encoding = Encoding.GetEncoding("Big5"); break; default: encoding = Encoding.UTF8; break; } //流操作 Stream stream = response.GetResponseStream(); StreamReader sr = new StreamReader(stream,encoding); string content = sr.ReadToEnd(); File.WriteAllText("1.html", content, Encoding.UTF8); //關閉釋放資源 stream.Close(); sr.Close(); response.Close(); return content; } else { MessageBox.Show("響應失敗!"); return string.Empty; } }
然後在點擊按鈕事件中調用該函數即可:webBrowser1.DocumentText = GetHTMLbyWebRequest(textBox1.Text.Trim());就能實現訪問亂碼的網站,但網站還是有一個問題:在訪問sohu時是亂碼,其他網站基本都能正常訪問.這讓我有陷入思考中.下麵是訪問google,同時在該函數中最後添加File.WriteAllText("text.html", content, Encoding.UTF8);還能獲取保存靜態頁麵.
同時也可以采用動態方法獲取網頁的字符集,在采用對應的編碼方式進行讀取.可以參看下麵文章:https://blog.csdn.net/xx530713660/article/details/6310121其核心代碼是:
//動態獲取網頁編碼方式並讀取 Encoding encoding = Encoding.GetEncoding(webBrowser.Document.Encoding); StreamReader stream = new StreamReader(webBrowser.DocumentStream, encoding); string conten = stream.ReadToEnd();
四.總結
文章主要是針對我在采用WebBrowser編寫簡單瀏覽器時遇到的中文亂碼問題,通常會顯示為"口口口"或"???",不同的編碼方式ISO-8859-1、GBK、Big5、utf-8采用相應的編碼方式即可避免.文章以PHP+MySQL遇到的中文亂碼開頭,這裏也以它結尾,在PHP+MySQL中需要注意兩個方麵:(1).PHP網頁|MySQL|Apache|瀏覽器中|服務器對應的編碼方式一致,就會避免亂碼問題,其中utf-8對應utf-8,gb2312(國標碼)對應txt中ANSI編碼方式;
(2).注意有無BOM問題(為識別Unicode文件,以U+FEFF字符開頭,作為字節順序標記byte-order mark,BOM來識別文件中使用的編碼和字節順序),通常Apache中charset設置為utf-8,所以采用UltraEdit設置文件格式為utf-8無BOM另存為即可.
希望文章能幫助到大家,如果文章中有錯誤或不足之處,請大家海涵!
(By:Eastmount 2013-9-23 21點 https://blog.csdn.net/eastmount)
最後更新:2017-04-03 15:21:51