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
两种方法都是每次都只读一个字节,不知道效率如何,不过总算是解决了困扰已久的图标显示失真的问题,还学到了不少东西!
本文原创发表于博客园,作者为何朝阳,博客http://www.cnblogs.com/hechaoyang/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则视为侵权。

浙公网安备 33010602011771号