Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/261.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# HttpWebResponse的编码问题_C#_Encoding - Fatal编程技术网

C# HttpWebResponse的编码问题

C# HttpWebResponse的编码问题,c#,encoding,C#,Encoding,以下是代码片段: 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();

以下是代码片段:

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();
问题在于,如果我使用以下工具进行测试:

并非所有的“é”都表现得很好。我尝试将ASCII更改为UTF8,但它仍然显示错误。我已经在浏览器中测试了html文件,浏览器可以很好地显示html文本,所以我很确定问题出在我下载html文件的方法上

我应该换什么

拆下固定的影像棚链接


更新1:代码和测试文件更改首先,编写代码的更简单方法是使用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();
    }
}
然后,“只是”找到正确编码的问题。你是如何创建这个文件的?如果使用记事本,那么您可能需要
编码。默认值
——但这显然不便于携带,因为这是您电脑的默认编码

在运行良好的web服务器中,响应将在其头中指示编码。话虽如此,在某些情况下,响应头有时声明一件事,HTML声明另一件事。

默认情况下,如果未在服务器的内容类型头中指定字符集,则字符集为“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();
            }
        }
    }

如果您不想两次下载该页面,我使用修改了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;
}

我在WireShark的帮助下研究了同样的问题,WireShark是一个伟大的协议分析器。我认为httpWebResponse类存在一些设计缺陷。事实上,整个消息实体是在您第一次调用HttpWebRequest类的GetResponse()方法时下载的,但是框架没有地方在HttpWebResponse类或其他地方保存数据,因此,您必须第二次获得响应流。

从WebRequest请求网页“www.google.fr”时,仍然存在一些问题

我用Fiddler检查了原始请求和响应。问题来自谷歌服务器。响应HTTP头被设置为charset=ISO-8859-1,文本本身用ISO-8859-1编码,而HTML表示charset=UTF-8。这是不连贯的,会导致编码错误

经过多次测试,我终于找到了解决办法。只需添加:

myHttpWebRequest.UserAgent = "Mozilla/5.0";

下载到您的代码中,Google响应将神奇地完全变成UTF-8。

这是一次下载的代码

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();

这里有一些很好的解决方案,但它们似乎都试图解析内容类型字符串中的字符集。这里有一个使用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);

“é”应该仍然有效,即使在ASCII中也是如此。您是在输出到一个文件并确定它不起作用,还是在快速观察中中断指向返回的sb.ToString()并查看它并确定它失败了?不,在ASCII中,尖锐的重音永远不会起作用,因为ASCII最多只包含127个Unicode(以防万一有人想反驳这一点并谈论“扩展ASCII”)-看)这里的zabulus答案是什么?看起来简单多了:这和Jon 4年前的回答差不多:)事实上,我正试图在世界各地获取文件,但我得到了一些不好的输出(PNG文件格式不正确),文本写得不好(所有字符都像“é”)。如果你试图读取任意HTML,你需要检查标题,有时还需要检查HTML的开头(它可以像XML一样宣传编码)。有时你必须检测到它可能不正确,然后通过启发式进行猜测!好的,我来看看标题。我在玩你的代码,StreamReader(resStream,true)不起作用(应该用字节找到编码…)我将尝试从标题中获取它。我将稍后发布。只是好奇您是否了解多年来“在服务器不提供字符集的情况下确定要使用的字符集”有多复杂(请参阅Alex的回答)@LynnCrumbling:没有,真的没有。我认为这应该标记为答案。这实际上从任何网页获取编码并正确解码。但问题是,这在Windows phone中不起作用,因为它的响应实现不支持响应。CharacterSetBetween!正是我要找的。我已经有了一个循环重试意外错误,所以我只需要将charset和realcharset转换为局部变量,以避免额外的请求声明。现在是2020年,这不再是真的。事实上,这变得非常复杂。要了解此beast的完整摘要,请查看。TL;dr:RFC 7231现在说没有定义的编码,除非您是XML内容,在这种情况下,它是美国ascii码。但是,当然,还有更多。NET 4和更高版本应该有一个Stream.CopyTo(Stream)方法来简化它。为什么必须将缓冲区大小设置为1024?不可能一次读取整个流吗?为什么1024?为什么不将其设置得更大?