Csharp/C#教程:基于字符集、字符编码与HTTP编码解码之万象详解分享

在日常编写代码过程中,常常会碰到乱码问题,一个典型的情况是浏览网页,如果网站开发者缺少经验,就会带来这种令人头疼的问题。要了解乱码的症结,我们就得从字符集和字符编码说起,先来看看它们到底是什么:
1:字符集:是一个系统支持的所有抽象字符的集合。字符是各种文字和符号的总称,包括各国家文字、标点符号、图形符号、数字等。
2:字符编码:是一套法则,最常规的理解就是:让程序根据这个法则对应到相应的字符集中将byte[]存取为string。
现在,我们要来看看这些东西在.NET中对应的是什么。

一:字符集和字符编码
如果想得到全部的字符集,则使用System.Text.Encoding.GetEncodings()方法,以下代码用于列出.Net支持的全部字符集:
代码如下:
foreach(variteminEncoding.GetEncodings())
{
   Console.WriteLine(item.Name);
}

字符串在进行如网络传输等场景时,要先转为byte[]。但是,首先,不同的字符编码规则,所转换生成的byte[]是不一样的。所以,再将byte[]转换回string的时候,要依据原先的字符编码规则。有如下几种情况能导致“乱码”的产生:
1:stringtobyte[]和byte[]tostring,使用了不同的字符编码规则;
2:byte[]tostring的时候,当前宿主环境没有对应的字符集;

示例:
代码如下:
stringoriginalString=”HelloTest,测试!”;
byte[]utf8Bytes=Encoding.UTF8.GetBytes(originalString);
stringutf8String=Encoding.UTF8.GetString(utf8Bytes);
stringerrorString=Encoding.ASCII.GetString(utf8Bytes);

观察Encoding类,实际上象上面UTF8这样的属性,只有几个,这些是最常用的字符集,要获取其它,如gb2312这样的字符集,则需要象如下这样来获得:
代码如下:
byte[]gbBytes=Encoding.GetEncoding(“gb2312”).GetBytes(originalString);
stringutf8String=Encoding.GetEncoding(“gb2312”).GetString(gbBytes);

二:典型应用场景之HttpWebResponse

很多人都作过页面抓取功能,HttpWebResponse就会比较熟悉,当然如果不嫌麻烦,也可以用Socket实现,但是同时要解析很多属性以及处理象重定向之类的诸多问题。
 

2.1httpheader和httpcontent是什么?
浏览一个网页,使用很多工具,或者使用.Net中的某些类进行抓取,都给我们结构化为Http头和正文这样的信息,其实,当我们发送一个请求,服务器返回给我们的是一串byte[],我们完全可以自己去从这串byte[]解析出httpheader和httpcontent,它们之间其实仅仅非常简单的以两个/r/n/分割开而已,历史上有著名的CRLF攻击,CR就是r,LF就是n,就利用的是这个规则。

2.2我们如何察看httpheader,httpcontent?
其实很简单,既然这些都是byte[],所以,我们只要知道这段byte[]正确的字符编码规则,就能得到我们所需要看到的html(html就是字符串而已)。使用HttpWebResponse这个类,就能请求一个url,该类自动为我们解析出了httpheader,有意思的是,它没有给我们解析出content,所以,我们需要自己完成正文的byte[]tostring。
 

2.3httpcontenttostring的具体做法
好的,实际上,httpheader 中已经告诉了我们一些字符集编码相关的信息,我们可能感兴趣,以及会混淆的这些http头如下:
代码如下:
Content-Type:WEB服务器告诉浏览器自己响应的对象的类型和字符集。例如:Content-Type:text/html;charset=’gb2312’;
Content-Encoding:WEB服务器表明自己使用了什么压缩方法(gzip,deflate)压缩响应中的对象。例如:Content-Encoding:gzip。这里我要多说一点,这个Content-Encoding的Httpheader会令人混淆,极度容易让人理解成是字符集或字符编码信息;

那么,这些Http头在HttpWebResponse中是怎么代表的呢?
代码如下:
HttpWebResponse.Content-Type对应的是Http头的Content-Type比如”text/html;”后的那个Charset,实际是和HttpWebResponse.Charaterset是一致的。但是如果前者无,则后者

一般会指定一个默认的HttpWebResponse.Charaterset,默认为”iso-8859-1″。
HttpWebResponse.ContentEncoding代表的是http头中Content-Encoding,与此类似的,还有一个http头,为Transfer-Encoding。注意,很恶心的一点是

HttpResponse.ContentEncoding跟HttpWebResponse.ContentEncoding代表的不是一个东西,它和HttpResponse.Charaterset在MSDN上是一致的解释。

根据上面的说法,似乎下面的代码就能得到httpcontent的字符编码规则:
代码如下:
returnEncoding.GetEncoding(
  string.IsNullOrEmpty(HttpWebResponse.Charaterset)?
“iso-8859-1”:HttpWebResponse.Charaterset

但是,这里有一个很重要的但是,如果你尝试从Http头或者HttpWebResponse所给我的这些字符编码信息或属性去解码正文content的话,很可能马上就会迎来一个大大的挫折。我们很可能会发现以下几个可悲的事实:
代码如下:
1:http头的Content-Type中没有charset信息;
2:HttpWebResponse.Charaterset是空的;
3:http头的Content-Type和HttpWebResponse.Charaterset是不一致的;
4:http头的Content-Type和HttpWebResponse.Charaterset是一致的,但是解码还是错的;
5:尝试用”iso-8859-1″解码也是错的。

2.4为什么还是有乱码问题?BOM能解决一切?

之所以碰到上述就是C#学习教程:基于字符集、字符编码与HTTP编码解码之万象详解分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)

本文来自网络收集,不代表计算机技术网立场,如涉及侵权请点击右边联系管理员删除。

如若转载,请注明出处:https://www.ctvol.com/cdevelopment/904570.html

(0)
上一篇 2021年10月21日
下一篇 2021年10月21日

精彩推荐