[英]Encoding trouble with HttpWebResponse
以下是代碼片段:
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(request.RawUrl);
WebRequest.DefaultWebProxy = null;//Ensure that we will not loop by going again in the proxy
HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse();
string charSet = response.CharacterSet;
Encoding encoding;
if (String.IsNullOrEmpty(charSet))
encoding = Encoding.Default;
else
encoding = Encoding.GetEncoding(charSet);
StreamReader resStream = new StreamReader(response.GetResponseStream(), encoding);
return resStream.ReadToEnd();
問題是如果我測試: http : //www.google.fr
所有“é”都表現不佳。 我試圖將ASCII更改為UTF8,但仍然顯示錯誤。 我在瀏覽器中測試了html文件,瀏覽器顯示了html文本,所以我很確定問題出在我用來下載html文件的方法中。
我應該改變什么?
刪除了死的ImageShack鏈接
如果未在服務器的內容類型標頭中指定(與HTML中的“charset”元標記不同),則CharacterSet默認為“ISO-8859-1”。 我將HttpWebResponse.CharacterSet與HTML的charset屬性進行比較。 如果它們不同 - 我使用HTML中指定的字符集重新讀取頁面,但這次使用了正確的編碼。
看代碼:
string strWebPage = "";
// create request
System.Net.WebRequest objRequest = System.Net.HttpWebRequest.Create(sURL);
// get response
System.Net.HttpWebResponse objResponse;
objResponse = (System.Net.HttpWebResponse)objRequest.GetResponse();
// get correct charset and encoding from the server's header
string Charset = objResponse.CharacterSet;
Encoding encoding = Encoding.GetEncoding(Charset);
// read response
using (StreamReader sr =
new StreamReader(objResponse.GetResponseStream(), encoding))
{
strWebPage = sr.ReadToEnd();
// Close and clean up the StreamReader
sr.Close();
}
// Check real charset meta-tag in HTML
int CharsetStart = strWebPage.IndexOf("charset=");
if (CharsetStart > 0)
{
CharsetStart += 8;
int CharsetEnd = strWebPage.IndexOfAny(new[] { ' ', '\"', ';' }, CharsetStart);
string RealCharset =
strWebPage.Substring(CharsetStart, CharsetEnd - CharsetStart);
// real charset meta-tag in HTML differs from supplied server header???
if(RealCharset!=Charset)
{
// get correct encoding
Encoding CorrectEncoding = Encoding.GetEncoding(RealCharset);
// read the web page again, but with correct encoding this time
// create request
System.Net.WebRequest objRequest2 = System.Net.HttpWebRequest.Create(sURL);
// get response
System.Net.HttpWebResponse objResponse2;
objResponse2 = (System.Net.HttpWebResponse)objRequest2.GetResponse();
// read response
using (StreamReader sr =
new StreamReader(objResponse2.GetResponseStream(), CorrectEncoding))
{
strWebPage = sr.ReadToEnd();
// Close and clean up the StreamReader
sr.Close();
}
}
}
首先,編寫該代碼的更簡單方法是使用StreamReader和ReadToEnd:
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(myURL);
using (HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse())
{
using (Stream resStream = response.GetResponseStream())
{
StreamReader reader = new StreamReader(resStream, Encoding.???);
return reader.ReadToEnd();
}
}
那么“只是”找到正確的編碼問題。 你是怎么創建這個文件的? 如果它是記事本,那么你可能想要Encoding.Default
- 但這顯然不是便攜式的,因為它是你 PC的默認編碼。
在運行良好的Web服務器中,響應將在其標頭中指示編碼。 話雖如此,在某些情況下,響應標題有時會聲稱一件事,HTML聲稱另一件事。
如果您不想兩次下載頁面,我會使用如何將WebResponse放入內存流中稍微修改Alex的代碼? 。 這是結果
public static string DownloadString(string address)
{
string strWebPage = "";
// create request
System.Net.WebRequest objRequest = System.Net.HttpWebRequest.Create(address);
// get response
System.Net.HttpWebResponse objResponse;
objResponse = (System.Net.HttpWebResponse)objRequest.GetResponse();
// get correct charset and encoding from the server's header
string Charset = objResponse.CharacterSet;
Encoding encoding = Encoding.GetEncoding(Charset);
// read response into memory stream
MemoryStream memoryStream;
using (Stream responseStream = objResponse.GetResponseStream())
{
memoryStream = new MemoryStream();
byte[] buffer = new byte[1024];
int byteCount;
do
{
byteCount = responseStream.Read(buffer, 0, buffer.Length);
memoryStream.Write(buffer, 0, byteCount);
} while (byteCount > 0);
}
// set stream position to beginning
memoryStream.Seek(0, SeekOrigin.Begin);
StreamReader sr = new StreamReader(memoryStream, encoding);
strWebPage = sr.ReadToEnd();
// Check real charset meta-tag in HTML
int CharsetStart = strWebPage.IndexOf("charset=");
if (CharsetStart > 0)
{
CharsetStart += 8;
int CharsetEnd = strWebPage.IndexOfAny(new[] { ' ', '\"', ';' }, CharsetStart);
string RealCharset =
strWebPage.Substring(CharsetStart, CharsetEnd - CharsetStart);
// real charset meta-tag in HTML differs from supplied server header???
if (RealCharset != Charset)
{
// get correct encoding
Encoding CorrectEncoding = Encoding.GetEncoding(RealCharset);
// reset stream position to beginning
memoryStream.Seek(0, SeekOrigin.Begin);
// reread response stream with the correct encoding
StreamReader sr2 = new StreamReader(memoryStream, CorrectEncoding);
strWebPage = sr2.ReadToEnd();
// Close and clean up the StreamReader
sr2.Close();
}
}
// dispose the first stream reader object
sr.Close();
return strWebPage;
}
這里有一些很好的解決方案,但它們似乎都試圖從內容類型字符串中解析字符集。 這是使用System.Net.Mime.ContentType的解決方案,它應該更可靠,更短。
var client = new System.Net.WebClient();
var data = client.DownloadData(url);
var encoding = System.Text.Encoding.Default;
var contentType = new System.Net.Mime.ContentType(client.ResponseHeaders[HttpResponseHeader.ContentType]);
if (!String.IsNullOrEmpty(contentType.CharSet))
{
encoding = System.Text.Encoding.GetEncoding(contentType.CharSet);
}
string result = encoding.GetString(data);
這是下載一次的代碼。
String FinalResult = "";
HttpWebRequest Request = (HttpWebRequest)System.Net.WebRequest.Create( URL );
HttpWebResponse Response = (HttpWebResponse)Request.GetResponse();
Stream ResponseStream = Response.GetResponseStream();
StreamReader Reader = new StreamReader( ResponseStream );
bool NeedEncodingCheck = true;
while( true )
{
string NewLine = Reader.ReadLine(); // it may not working for zipped HTML.
if( NewLine == null )
{
break;
}
FinalResult += NewLine;
FinalResult += Environment.NewLine;
if( NeedEncodingCheck )
{
int Start = NewLine.IndexOf( "charset=" );
if( Start > 0 )
{
Start += "charset=\"".Length;
int End = NewLine.IndexOfAny( new[] { ' ', '\"', ';' }, Start );
Reader = new StreamReader( ResponseStream, Encoding.GetEncoding(
NewLine.Substring( Start, End - Start ) ) ); // Replace Reader with new encoding.
NeedEncodingCheck = false;
}
}
}
Reader.Close();
Response.Close();
我在WireShark的幫助下研究了同樣的問題,這是一個很棒的協議分析器。 我認為httpWebResponse類有一些設計簡介。 事實上,在您第一次調用HttpWebRequest類的GetResponse()方法時下載了整個消息實體,但是框架沒有地方可以將數據保存在HttpWebResponse類或其他地方,導致您必須獲取響應流第二次。
從WebRequest請求網頁“www.google.fr”時仍存在一些問題。
我用Fiddler檢查了原始請求和響應。 問題來自Google服務器。 響應HTTP標頭設置為charset = ISO-8859-1,文本本身用ISO-8859-1編碼,而HTML表示charset = UTF-8。 這是不連貫的並導致編碼錯誤。
經過多次測試,我找到了解決方法。 只需添加:
myHttpWebRequest.UserAgent = "Mozilla/5.0";
對於您的代碼,Google Response將神奇地完全成為UTF-8。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.