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();
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");    //GB2312url编码处理
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);还能获取保存静态页⾯.
//动态获取⽹页编码⽅式并读取
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点)