28

コードのスニペットは次のとおりです。

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 リンクを削除

更新 1: コードとテスト ファイルが変更されました

4

7 に答える 7

29

CharacterSet は、サーバーのコンテンツ タイプ ヘッダーで指定されていない場合、デフォルトで「ISO-8859-1」です (HTML の「charset」メタ タグとは異なります)。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();
            }
        }
    }
于 2010-11-19T20:55:12.273 に答える
26

まず、そのコードを簡単に記述する方法は、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();
    }
}

次に、正しいエンコーディングを見つけるのは「ただ」の問題です。どのようにファイルを作成しましたか? メモ帳を使用している場合は、おそらく必要ですが PCEncoding.Defaultのデフォルトのエンコーディングであるため、明らかに移植性がありません。

正常に動作している Web サーバーでは、応答のヘッダーにエンコーディングが示されます。そうは言っても、場合によっては、応答ヘッダーが 1 つのことを主張し、HTML が別のことを主張することがあります。

于 2008-10-22T21:23:02.537 に答える
16

ページを 2 回ダウンロードしたくない場合に備えて、「How do I put a WebResponse into a memory stream?」を使用して 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;
}
于 2012-03-23T15:25:53.323 に答える
3

ここにはいくつかの良い解決策がありますが、それらはすべて、コンテンツ タイプの文字列から文字セットを解析しようとしているようです。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);
于 2016-09-12T20:36:29.490 に答える
0

優れたプロトコル アナライザーである WireShark の助けを借りて、同じ問題を調査しました。httpWebResponse クラスにはいくつかの設計上の問題があると思います。実際、最初に HttpWebRequest クラスの GetResponse() メソッドを呼び出したときにメッセージ エンティティ全体がダウンロードされましたが、フレームワークには HttpWebResponse クラスまたは他の場所にデータを保持する場所がないため、応答ストリームを取得する必要があります。 2回目。

于 2013-01-25T14:10:42.310 に答える
0

WebRequest から Web ページ「www.google.fr」を要求する場合、まだいくつかの問題があります。

Fiddler で生のリクエストとレスポンスを確認しました。問題は Google サーバーに由来します。応答 HTTP ヘッダーは charset=ISO-8859-1 に設定され、テキスト自体は ISO-8859-1 でエンコードされますが、HTML は charset=UTF-8 と表示されます。これは一貫性がなく、エンコード エラーにつながります。

多くのテストの後、私は回避策を見つけることができました。追加するだけです:

myHttpWebRequest.UserAgent = "Mozilla/5.0";

コードに追加すると、Google レスポンスは魔法のように完全に UTF-8 になります。

于 2015-12-19T04:59:38.200 に答える