代码改变世界

C#中FileStream.Read方法中buffer的相关问题

2010-10-29 22:08  何朝阳  阅读(1922)  评论(3)    收藏  举报

  最近在做浏览器的时候,涉及到显示网站图标的问题,因而需要从网上下载各网站的图标,但是显示效果总是不令人满意,大部分显示正常,总有那么几个图标显示严重失真,最开始的时候以为是ImageList的原因,将ImageList的ColorDepth设置为Depth32Bit,效果还是一样,没什么变化,百度了好久也不见答案,刚才在看浏览器下载好的图标时,无意之中发现:图标的大小都是1Kb的整数倍(图①,图②),突然想起是不是下载图标时候出现了问题,因为我的buffer就设置的1024,想到这里,立马打开DownloadFile函数:

图① 下载好的图标 

图② 图标大小为1024字节的整数倍

 

从网上下载文件
1 #region 从网上下载文件
2 /// <summary>
3 /// 从网上下载文件
4 /// </summary>
5 /// <param name="strUrl">URL地址</param>
6 /// <param name="strSavePath">下载文件保存路径</param>
7   public static bool DownloadFile(string strUrl, string strSavePath)
8 {
9 try
10 {
11 Uri u = new Uri(strUrl);
12 HttpWebRequest mRequest = (HttpWebRequest)WebRequest.Create(u);
13 mRequest.Method = "GET";
14 mRequest.ContentType = "application/x-www-form-urlencoded";
15 HttpWebResponse wr = (HttpWebResponse)mRequest.GetResponse();
16 Stream sIn = wr.GetResponseStream();
17 FileStream fs = new FileStream(strSavePath, FileMode.Create, FileAccess.Write);
18 byte[] buffer = new byte[1024];
19 while (sIn.Read(buffer, 0, buffer.Length) > 0)
20 {
21 fs.Write(buffer, 0, buffer.Length);
22 }
23 sIn.Close();
24 wr.Close();
25 fs.Close();
26 return true;
27 }
28 catch
29 {
30 return false;
31 }
32 }
33 #endregion

  也没看出有什么问题,但直觉应该是和buffer大小的设置有关,百度了一下说:“buffer长度较小,不会一次从fs中读取所有数据。那么在倒数第二次取完byte之后,最后一次可能会出现剩余的待取字节不足buffer长度的情况,buffer只有前半部分被更新,后面剩余了倒数第二次取得的字节。”(http://zhidao.baidu.com/question/53994819.html),也就是说最后一次读写数据时候不足1024字节的话,就会有冗余的数据写入图标文件,从而破坏了图标文件,所以最后得到的图标文件大小都是1024字节的整数倍,所以图标显示失真的问题就出在下载图标的函数里面,解决办法如下:

  方法①:将上面代码中18行改成“byte[] buffer = new byte[1];”,这样就不会有冗余的数据写入图标文件;

  方法②:将代码改为:

1 #region 从网上下载文件
2 /// <summary>
3 /// 从网上下载文件
4 /// </summary>
5 /// <param name="strUrl">URL地址</param>
6 /// <param name="strSavePath">下载文件保存路径</param>
7 public static bool DownloadFile(string strUrl, string strSavePath)
8 {
9 try
10 {
11 Uri u = new Uri(strUrl);
12 HttpWebRequest mRequest = (HttpWebRequest)WebRequest.Create(u);
13 mRequest.Method = "GET";
14 mRequest.ContentType = "application/x-www-form-urlencoded";
15 HttpWebResponse wr = (HttpWebResponse)mRequest.GetResponse();
16 Stream sIn = wr.GetResponseStream();
17 FileStream fs = new FileStream(strSavePath, FileMode.Create, FileAccess.Write);
18 //byte[] buffer = new byte[1];
19 //while (sIn.Read(buffer, 0, buffer.Length) > 0)
20 //{
21 // fs.Write(buffer, 0, buffer.Length);
22 //}
23 int b;
24 while ((b = sIn.ReadByte()) != -1)
25 {
26 fs.WriteByte((byte)b);
27 }
28 sIn.Close();
29 wr.Close();
30 fs.Close();
31 return true;
32 }
33 catch
34 {
35 return false;
36 }
37 }
38 #endregion

  两种方法都是每次都只读一个字节,不知道效率如何,不过总算是解决了困扰已久的图标显示失真的问题,还学到了不少东西!