在使用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());
}
其中最简单的方法是先获取其指定网页的字符集,在根据它的字符集采用相应的编码方式进行解码读取.我们采用下面代码获取该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字符集,因此我们可以设置相应的函数,直接调用函数实现显示内容:(代码感谢一位博主,http://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);还能获取保存静态页面.
同时也可以采用动态方法获取网页的字符集,在采用对应的编码方式进行读取.可以参看下面文章:http://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();