亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C# > 正文

基于字符集、字符編碼與HTTP編碼解碼之萬象詳解

2020-01-24 03:26:50
字體:
來源:轉載
供稿:網友

在日常編寫代碼過程中,常常會碰到亂碼問題,一個典型的情況是瀏覽網頁,如果網站開發者缺少經驗,就會帶來這種令人頭疼的問題。要了解亂碼的癥結,我們就得從字符集和字符編碼說起,先來看看它們到底是什么:
1:字符集:是一個系統支持的所有抽象字符的集合。字符是各種文字和符號的總稱,包括各國家文字、標點符號、圖形符號、數字等。
2:字符編碼:是一套法則,最常規的理解就是:讓程序根據這個法則對應到相應的字符集中將byte[]存取為string。
現在,我們要來看看這些東西在 .NET 中對應的是什么。

一:字符集和字符編碼
如果想得到全部的字符集,則使用 System.Text.Encoding.GetEncodings() 方法,以下代碼用于列出.Net支持的全部字符集:

復制代碼 代碼如下:

foreach (var item in Encoding.GetEncodings())
{
    Console.WriteLine(item.Name);
}

字符串在進行如網絡傳輸等場景時,要先轉為 byte[] 。但是,首先,不同的字符編碼規則,所轉換生成的byte[]是不一樣的。所以,再將byte[]轉換回string的時候,要依據原先的字符編碼規則。有如下幾種情況能導致“亂碼”的產生:
1:string to byte[] 和 byte[] to string,使用了不同的字符編碼規則;
2:byte[] to string 的 時候,當前宿主環境沒有對應的字符集;

示例:

復制代碼 代碼如下:

string originalString = "Hello Test, 測試!";
byte[] utf8Bytes = Encoding.UTF8.GetBytes(originalString);
string utf8String = Encoding.UTF8.GetString(utf8Bytes);
string errorString = Encoding.ASCII.GetString(utf8Bytes);

觀察Encoding類,實際上象上面UTF8這樣的屬性,只有幾個,這些是最常用的字符集,要獲取其它,如gb2312這樣的字符集,則需要象如下這樣來獲得:
復制代碼 代碼如下:

byte[] gbBytes = Encoding.GetEncoding("gb2312").GetBytes(originalString);
string utf8String = Encoding.GetEncoding("gb2312").GetString(gbBytes);

二:典型應用場景之 HttpWebResponse

很多人都作過頁面抓取功能, HttpWebResponse 就會比較熟悉,當然如果不嫌麻煩,也可以用 Socket 實現,但是同時要解析很多屬性以及處理象重定向之類的諸多問題。
 

2.1 http header 和http content是什么?
瀏覽一個網頁,使用很多工具,或者使用.Net中的某些類進行抓取,都給我們結構化為 Http 頭和正文這樣的信息,其實,當我們發送一個請求,服務器返回給我們的是一串 byte[],我們完全可以自己去從這串 byte[] 解析出 http header 和 http content,它們之間其實僅僅非常簡單的以兩個 /r/n/ 分割開而已,歷史上有著名的CRLF攻擊,CR就是/r,LF就是/n,就利用的是這個規則。


2.2 我們如何察看http header,http content?
其實很簡單,既然這些都是 byte[] ,所以,我們只要知道這段 byte[] 正確的字符編碼規則,就能得到我們所需要看到的 html (html就是字符串而已)。使用 HttpWebResponse 這個類,就能請求一個 url ,該類自動為我們解析出了 httpheader ,有意思的是,它沒有給我們解析出 content ,所以,我們需要自己完成正文的byte[] to string。
 

2.3 http content to string的具體做法
好的,實際上,httpheader  中已經告訴了我們一些字符集編碼相關的信息,我們可能感興趣,以及會混淆的這些http頭如下:

復制代碼 代碼如下:

Content-Type:WEB 服務器告訴瀏覽器自己響應的對象的類型和字符集。例如:Content-Type: text/html; charset='gb2312' ;
Content-Encoding:WEB 服務器表明自己使用了什么壓縮方法(gzip,deflate)壓縮響應中的對象。例如:Content-Encoding:gzip 。這里我要多說一點,這個 Content-Encoding 的 Http header 會令人混淆,極度容易讓人理解成是字符集或字符編碼信息;

那么,這些 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上是一致的解釋。


根據上面的說法,似乎下面的代碼就能得到http content的字符編碼規則:
復制代碼 代碼如下:

return Encoding.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能解決一切?

之所以碰到以上問題,其實僅僅是因為,服務器給我們傳回來的是byte[],而任何程序員在寫服務器端WEB程序的時候,都有可能有意或無意的轉碼出不規范的byte[]來。所以,如果我們嘗試從http頭的Content-Type和HttpWebResponse.Charaterset想要得到編碼規則,我們就敗了,我們敗在了有標準,但是沒人嚴格去執行標準。

有一些頗具迷惑性的API試圖在告訴我們,使用我你就能得到該流正確的Encoding了,比如,StreamReader.CurrentEncoding,我們可以把HttpWebResponse的GetResponse中讀取到

byte[],放置到MemoryStream中,然后利用如下代碼:

復制代碼 代碼如下:

StreamReader sr = new StreamReader(memoryStream, true)
return sr.CurrentEncoding;

似乎就可以得到Encoding了,其實非也,注意StreamReader構造器的第二個參數,為detectEncodingFromByteOrderMarks。ByteOrderMarks是什么呢?解釋如下:
復制代碼 代碼如下:

BOM(byte-order mark),即字節順序標記,它是插入到以UTF-8、UTF16或UTF-32編碼Unicode文件開頭的特殊標記,用來識別Unicode文件的編 碼類型。對于UTF-8來說,BOM并不是必須的,因為BOM用來標記多字節編碼文件的編碼類型和字節順序(big-endian或little- endian)。

這表明了什么呢?表明了如果你的字節流未含有BOM,或者即便包含了BOM,但是字節流不是unicode-based的Encoding,則依舊不能得到正確的Encoding,具體我們也可以看StreamReader的源碼來得到驗證。這個萬惡的CurrentEncoding屬性并沒有告訴你它的前提條件。


2.5 關于本例的一點補充
以上字節流的編碼解碼,很多地方用了Response做例子,但是,以上解碼針對的是非壓縮的Response,如果服務器已經對http流進行了壓縮(其壓縮格式在Content-Encoding中指明了),我們就得先解壓縮,再解碼Response流,然后再解碼正文。考慮到本文的主題,特意剪裁了對于 Response 流的解壓過程。


2.6 關于正確解碼的嘗試

有很多人嘗試從byte[]本身去解析和判斷編碼規則的API,如:codeproject上也有相關的文章,但是可悲的事實是:并沒有一種完美的方法來自動判斷byte[]的編碼規則。還記得我們的瀏覽器(如IE)的編碼設置中的“自動選擇”嗎,其實這個自動選擇的錯誤率還是蠻高的。所以,對于字節流的生成者,如BS程序開發者,可以通過規范輸出:聲明charset和編碼規范的方式,這樣才能讓解析者(如瀏覽器)解析的時候盡可能的少出現亂碼。 

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美国产激情18| 日韩av最新在线| 欧美日韩国产中文字幕| 国产视频精品免费播放| 日韩亚洲成人av在线| 欧美孕妇孕交黑巨大网站| 亚洲一区二区三区xxx视频| 精品久久久久久久久久久久久久| 精品欧美一区二区三区| 91精品久久久久久久久久入口| 欧美美女15p| 狠狠久久亚洲欧美专区| 色99之美女主播在线视频| 亚洲天堂色网站| 欧美另类极品videosbestfree| 亚洲自拍偷拍网址| 中文字幕自拍vr一区二区三区| 亚洲男人天堂2024| 九九热这里只有精品免费看| 97超级碰碰碰| 久久久999国产精品| 国产日产久久高清欧美一区| 亚洲精品免费一区二区三区| 中国人与牲禽动交精品| 日韩av在线网页| 色无极影院亚洲| 国产v综合v亚洲欧美久久| 国产剧情久久久久久| 亚洲欧美另类自拍| 欧美日产国产成人免费图片| 欧美视频在线观看免费| 日韩精品视频免费在线观看| 亚洲偷熟乱区亚洲香蕉av| 国产亚洲人成a一在线v站| 中文字幕少妇一区二区三区| 欧美精品做受xxx性少妇| xxxx欧美18另类的高清| 国产精品久在线观看| 亚洲性生活视频| 国产日韩欧美在线视频观看| 中文字幕精品视频| 欧美成人精品一区二区| 91精品国产91久久久久| 欧美成人国产va精品日本一级| 亚洲精品成人网| 亚洲欧美国产高清va在线播| 国产精品视频地址| 国产91色在线|免| 亚洲国产又黄又爽女人高潮的| 久久久久这里只有精品| 在线播放国产精品| 日本19禁啪啪免费观看www| 欧美日韩国产黄| 日韩欧美国产网站| 97久久精品视频| 亚洲欧洲日本专区| 欧美性xxxx18| 欧美成人在线免费视频| 欧美日韩福利在线观看| 狠狠躁夜夜躁久久躁别揉| 国产精品高清免费在线观看| 久久久久久久久91| 欧美激情精品久久久久久大尺度| 8090成年在线看片午夜| 色综合色综合网色综合| 国产97在线视频| 俺也去精品视频在线观看| 久久久久久综合网天天| 丰满岳妇乱一区二区三区| 欧美性开放视频| 亚洲www在线观看| 久久久亚洲欧洲日产国码aⅴ| 国产精品爽爽爽爽爽爽在线观看| 亚洲成人激情在线| 亚洲视频axxx| 亚洲国产高清高潮精品美女| 欧美极品在线播放| 国产精品极品尤物在线观看| 91青草视频久久| 一区二区三区在线播放欧美| 91精品国产综合久久香蕉最新版| 8050国产精品久久久久久| 国产精品扒开腿做| 欧美激情二区三区| 免费成人高清视频| 黑人狂躁日本妞一区二区三区| 日韩福利伦理影院免费| 亚洲免费av电影| 久久久这里只有精品视频| 97婷婷大伊香蕉精品视频| 国产精品影院在线观看| 亚洲女人天堂视频| 精品国产欧美成人夜夜嗨| 欧美亚洲第一区| 91大神在线播放精品| 久久99国产精品自在自在app| 成人综合网网址| 欧美理论片在线观看| 97国产精品人人爽人人做| 92福利视频午夜1000合集在线观看| 欧美午夜影院在线视频| 久久精品亚洲精品| 亚洲一级一级97网| 久热精品视频在线免费观看| 91色视频在线观看| 中日韩美女免费视频网址在线观看| 91美女片黄在线观| 国产成人aa精品一区在线播放| 国产91在线高潮白浆在线观看| 欧美在线激情视频| 精品亚洲国产成av人片传媒| 奇米4444一区二区三区| 一区二区在线视频| 亚洲人成五月天| 国产成人综合一区二区三区| 久久综合伊人77777蜜臀| 国产精品视频白浆免费视频| 欧美日本啪啪无遮挡网站| 91精品国产99久久久久久| 精品久久久久久亚洲国产300| 成人国产精品一区二区| 日韩一区二区三区xxxx| 国产精品网站大全| 日韩av大片免费看| 一本色道久久综合狠狠躁篇怎么玩| 国产黑人绿帽在线第一区| 亚洲成人精品视频在线观看| 97精品一区二区视频在线观看| 亚洲精品丝袜日韩| 国产精品一区二区三区久久久| 555www成人网| 国产精品大陆在线观看| 色偷偷偷综合中文字幕;dd| 日韩欧美主播在线| 丝袜亚洲另类欧美重口| 久久精品99国产精品酒店日本| 精品国产区一区二区三区在线观看| 久久99青青精品免费观看| 一本色道久久综合亚洲精品小说| 亚洲欧美三级伦理| 亚洲理论在线a中文字幕| 免费不卡欧美自拍视频| 欧美一级淫片丝袜脚交| 7777免费精品视频| 欧美性生交xxxxx久久久| 在线播放精品一区二区三区| 国产精品99蜜臀久久不卡二区| 国产精品久久久久久久久男| 国内久久久精品| 亚洲欧洲日产国产网站| 久久久亚洲影院| 久久久久久久999| 最近2019免费中文字幕视频三| 欧美韩国理论所午夜片917电影| 欧美人成在线视频| 北条麻妃在线一区二区| 蜜月aⅴ免费一区二区三区| 91精品国产精品| 91精品国产电影| 亚洲色无码播放| 国产69久久精品成人看| 国产精品黄页免费高清在线观看| 欧美视频一二三| 日韩成人在线电影网|