如何解决HttpWebResponse乱码?

 我来答
锄似犁牛
推荐于2016-07-23 · 超过67用户采纳过TA的回答
知道答主
回答量:139
采纳率:50%
帮助的人:62.7万
展开全部
从浏览器来分析我们知道大多数时候浏览器都能够正确处理网页的编码,当我们使用浏览器浏览不同编码的中文网站时不会出现“乱码”,但有时候也会出现乱码,这是为什么呢?浏览器如何知道返回来的流是什么编码?为什么有时候浏览器也不能正确处理编码问题?浏览器很可能是通过两种方式来获得服务器返回流的字符编码。 首先,浏览器会从尝试从Http Header来获得字符串编码,如果得不到(有些服务器返回的Http Header中没有包含CharSet)则尝试从HTML的Meta标签中获得。如果有的网站做得实在太烂,Http Header和Html的Meta中都没有返回编码信息,那就有可能出现乱码。由于ASP.NET可以通过Response.CharSet和Response.ContentType来控制发送给客户端的字符编码信息,因此浏览器的这些行为是可以验证的。这篇文章有列出验证实验:CodePage、ContentEncoding、Charset、ContentType、meta charset 有什么区别?问题的抛出因此问题就在于如何获得HttpWebResponse返回的流的编码。对于Header里面的CharSet我们直接通过HttpWebResponse的属性CharacterSet即可得到——当然如果服务器没有返回则会得到可能一个不正确的字符编码“ISO-8859-1”。这个时候我们只有从字符串本身包含的meta标签来获得编码信息,如果字符串不包含meta标签或者meta标签里面没有CharSet,那问题就难办了。如何处理?原理很简单,上面的问题的抛出已经说明了如何处理。这里直接贴代码:internal static HttpFormResponse ReadResponse(WebRequest request){const int MaxTry = 3; int tryCount = 0; var httpFormResponse = new HttpFormResponse(); // Sometimes the external site can throw exception so we might // have to retry few more times while (string.IsNullOrEmpty(httpFormResponse.Response) && (tryCount < MaxTry)){try{using (WebResponse response = request.GetResponse()){PopulateHeadersAndCookies(response, httpFormResponse); var httpWebResponse = (HttpWebResponse) response; var charSet = httpWebResponse.CharacterSet; var buffer = GetBytes(httpWebResponse); httpFormResponse.Response = GetStringFromBuffer(buffer, charSet);}}catch (WebException){tryCount += 1; Thread.Sleep(200);}} return httpFormResponse; } private static byte[] GetBytes(WebResponse response){var length = (int)response.ContentLength; byte[] data; using (var memoryStream = new MemoryStream()){var buffer = new byte[0x100]; using (var rs = response.GetResponseStream()){for (var i = rs.Read(buffer, 0, buffer.Length); i > 0; i = rs.Read(buffer, 0, buffer.Length)){memoryStream.Write(buffer, 0, i);}} data = memoryStream.ToArray(); } return data; } private static string GetStringFromBuffer(byte[] buffer, string charSet){if (string.IsNullOrEmpty(charSet) || string.Compare(charSet, "ISO-8859-1") == 0){charSet = GetEncodingFromBody(buffer);} try{var encoding = Encoding.GetEncoding(charSet); var str = encoding.GetString(buffer); return str;}catch (Exception ex){Log.Exception(ex); return string.Empty;}} private static string GetEncodingFromBody(byte[] buffer){var regex = new Regex(@"<meta(\s+)http-equiv(\s*)=(\s*""?\s*)content-type(\s*""?\s+)content(\s*)=(\s*)""text/html;(\s+)charset(\s*)=(\s*)(?<charset>[a-zA-Z0-9-]+?)""(\s*)(/?)>", RegexOptions.IgnoreCase | RegexOptions.Compiled); var str = Encoding.ASCII.GetString(buffer); var regMatch = regex.Match(str); if (regMatch.Success){var charSet = regMatch.Groups["charset"].Value; return charSet; } return Encoding.ASCII.BodyName; } internal static void PopulateHeadersAndCookies(WebResponse webResponse, HttpFormResponse response){response.Headers.Add(webResponse.Headers); var httpWebResponse = webResponse as HttpWebResponse; if (httpWebResponse != null){foreach (Cookie cookie in httpWebResponse.Cookies){response.Cookies.Add(cookie.Name, cookie.Value);}}}其中关键的代码就是这几行:var httpWebResponse = (HttpWebResponse) response; var charSet = httpWebResponse.CharacterSet; var buffer = GetBytes(httpWebResponse); 我觉得最关键的就是var buffer = GetBytes(httpWebResponse); ,通过这行代码将流拷贝到byte数组中保存起来,当无法从Http Header中获得编码信息是就用ASCII编码从buffer中获得字符串。我们知道HTML的标签都是字母,使用ASCII编码虽然中文或者其他双字节字符会出现乱码,但是HTML标签还是能够解析出来。这样我们就可以检测HTML的meta标签从而获得charset。
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式