3

这是对我来说出现问题的第一个 Wikipedia 页面。当我使用 HttpWebResponse.GetResponseStream() 打开此页面https://en.wikipedia.org/wiki/London时,它充满了 mojibake。但是我的浏览器可以毫无问题地对其进行编码。

我使用了三种方法来下载文本文件。他们都得到不同的文件。

第一种方法下载了一个274851字节的文件

    string TargetUri = "https://en.wikipedia.org/wiki/London";

    HttpWebRequest queryPage = (HttpWebRequest)WebRequest.Create(TargetUri);

    queryPage.Credentials = CredentialCache.DefaultCredentials;

    using (HttpWebResponse response = (HttpWebResponse)queryPage.GetResponse())
    {

        using (Stream PageRawCode = response.GetResponseStream())
        {
            using (MemoryStream PageRawCodeDuplicate = new MemoryStream())
            {
                byte[] buffer = new byte[1024];
                int ByteCount;
                do
                {
                    ByteCount = PageRawCode.Read(buffer, 0, buffer.Length);
                    PageRawCodeDuplicate.Write(buffer, 0, ByteCount);
                } while (ByteCount > 0);

                PageRawCodeDuplicate.Seek(0, SeekOrigin.Begin);

                using (StreamReader CodeInUTF8 = new StreamReader(PageRawCodeDuplicate))
                {
                    string PageText = CodeInUTF8.ReadToEnd();
                    using (StreamWriter sw = new StreamWriter(@"E:\My Documents\Desktop\london1.html"))
                    {
                        sw.Write(PageText);
                    }
                }
            }
        }
    }

第二种方法是

    WebClient myWebClient = new WebClient();
    myWebClient.DownloadFile("https://en.wikipedia.org/wiki/London", @"E:\My Documents\Desktop\london2.html");

这个方法只下载了一个152.297字节的文件

第三种方法是打开https://en.wikipedia.org/wiki/London,并保存源代码文件。此方法将得到一个 1,746,420 字节的文件

我不明白为什么使用不同的方法获取文本文件会有这样的差异。

我使用 ASCII、BigEndianUnicode、Unicode、UTF32、UTF7、UTF8 来读取前 2 个文件。他们都没有正确显示代码。

然后我阅读了文件的十六进制代码。london1.html 的前 32 个字符是

1FEFBFBD0800000000000003EFBFBDEF

london2.html 的前 32 个字符是

1F8B0800000000000003ECFD4B8F1C49

显然他们不是<!DOCTYPE html>

这两个文件是什么?我什至不知道如何检查它们。

4

2 回答 2

0

您的代码中有一个简单的问题。你忘了刷新内存流。我还添加了第二个解决方案,它不会先将 Stream 复制到内存中......

如果我运行这个稍微修改过的代码,我会得到一个完整的 html 文件:

using (HttpWebResponse response = (HttpWebResponse)queryPage.GetResponse())
{

    using (Stream PageRawCode = response.GetResponseStream())
    {
        using (MemoryStream PageRawCodeDuplicate = new MemoryStream())
        {
            byte[] buffer = new byte[1024];
            int ByteCount;
            do
            {
                ByteCount = PageRawCode.Read(buffer, 0, buffer.Length);
                PageRawCodeDuplicate.Write(buffer, 0, ByteCount);
            } while (ByteCount > 0);

            // FLUSH!
            PageRawCodeDuplicate.Flush();

            PageRawCodeDuplicate.Seek(0, SeekOrigin.Begin);

            // Pick an encoding here
            using (StreamReader CodeInUTF8 = new StreamReader(
                                   PageRawCodeDuplicate, Encoding.UTF8))
            {
                string PageText = CodeInUTF8.ReadToEnd();
                using (StreamWriter sw = new StreamWriter(@"london1.html"))
                {
                    sw.Write(PageText);
                }
            }
        }
    }
}

直接复制流

using (HttpWebResponse response = (HttpWebResponse)queryPage.GetResponse())
{
    using (Stream PageRawCode = response.GetResponseStream())
    {
            using (StreamReader CodeInUTF8 = new StreamReader(
                                                      PageRawCode, Encoding.UTF8))
            {
                using (StreamWriter sw = new StreamWriter(@"london1.html"))
                {
                    while (!CodeInUTF8.EndOfStream)
                    {
                        sw.WriteLine(CodeInUTF8.ReadLine());
                    }
                 }
            }
    }
}
于 2013-09-15T19:28:01.407 回答
0

Finally mystery SOLVED! The text stream is a GZipStream. Using GZipStream decompress can read the code. http://msdn.microsoft.com/en-us/library/system.io.compression.gzipstream.aspx It's hard to imagine how much the browser does behind

于 2013-09-17T12:38:19.860 回答