[C#]实现文件复制[更新]实时显示进度条
来源:互联网 发布:杭州卓森网络怎么样 编辑:程序博客网 时间:2024/06/16 11:15
在复制更新文件时,如果想要实时的获得文件复制的进度,并显示在窗体的进度条上有许多方法,在寻找了一段资料后,我整理了一些别人的代码,获得到本篇的代码,代码实现了根据配置文件,复制文件列表的效果.思路其实很简单,就是异步的读取和写入流,在异步回调的方法中,响应窗体的进度条控件,所有注释都写在代码中了.
相关代码:http://download.csdn.net/source/880686
程序界面:
- int totalSize; //读取文件总大小
- int position; //当前读取位置
- int BUFFER_SIZE = 1024; //缓存大小
- XmlDocument xmldoc; //配置XML文件上下文
- private class _Copy
- {
- public string SrcFile; //源文件
- public string DstFile; //目标文件
- public Stream stream; //流文件
- public byte[] buffer; //缓存
- public int position; //当前文件复制位置
- public int Size; //当前文件总大小
- }
- List<_Copy> CopyList; //复制列表
- public Form1()
- {
- InitializeComponent();
- }
- private void Form1_Load(object sender, EventArgs e)
- {
- xmldoc = new XmlDocument();
- xmldoc.Load("config.xml"); //配置文件
- CopyList = new List<_Copy>(); //复制列表
- //获取所有更新列表
- XmlNodeList list;
- list = xmldoc.GetElementsByTagName("update");
- foreach (XmlNode node in list)
- {
- _Copy copy = new _Copy();
- //如果路径末尾没有/符号,则自动加上
- if (node["Path"].InnerText.Substring(node["Path"].InnerText.Length - 1, 1) != @"/")
- {
- copy.SrcFile = node["Path"].InnerText + @"/" + node["Name"].InnerText;
- }
- else
- {
- copy.SrcFile = node["Path"].InnerText + node["Name"].InnerText;
- }
- //目标文件地址
- copy.DstFile = Application.StartupPath + @"/" + node["Name"].InnerText;
- CopyList.Add(copy);
- }
- //如果更新列表没有值,则退出,运行程序
- if (CopyList.Count <= 0)
- {
- this.Close();
- return;
- }
- totalSize = 0;
- for (int i = 0; i < CopyList.Count; i++)
- {
- try
- {
- //文件不存在,继续下个文件
- if (!File.Exists(CopyList[i].SrcFile)) continue;
- //目标文件已经存在,先复制一个备份
- if (File.Exists(CopyList[i].DstFile))
- {
- File.Copy(CopyList[i].DstFile, CopyList[i].DstFile + "_upgrade", true);
- File.Delete(CopyList[i].DstFile);
- }
- FileStream fs = new FileStream(CopyList[i].SrcFile, FileMode.Open, FileAccess.Read);
- totalSize += (int)fs.Length;
- CopyList[i].Size = (int)fs.Length;
- CopyList[i].stream = fs;
- //这里是设置缓存的大小,可以根据需要修改逻辑
- BUFFER_SIZE = CopyList[i].Size / 50;
- if (BUFFER_SIZE < 10 * 1024)
- {
- BUFFER_SIZE = CopyList[i].Size / 2;
- }
- //缓存的大小要设置的比总大小要小,否则无法读取
- if (totalSize > BUFFER_SIZE)
- {
- CopyList[i].buffer = new byte[BUFFER_SIZE];
- //异步调用读取文件流
- CopyList[i].stream.BeginRead(CopyList[i].buffer, 0, BUFFER_SIZE,
- new AsyncCallback(AsyncCopyFile), CopyList[i]);
- }
- else
- {
- fs.Close();
- }
- }
- catch (Exception Ex)
- {
- //出错,恢复备份文件
- File.Copy(CopyList[i].DstFile + "_upgrade", CopyList[i].DstFile, true);
- MessageBox.Show("更新出错" + Ex.ToString());
- }
- }
- }
- private void AsyncCopyFile(IAsyncResult ar)
- {
- int readedLength;
- _Copy copy = (_Copy)ar.AsyncState;
- try
- {
- //锁顶文件流
- lock (copy.stream)
- {
- //当文件流读取完毕,获得读取的大小
- readedLength = copy.stream.EndRead(ar);
- }
- //写入文件
- FileStream fsWriter = new FileStream(copy.DstFile, FileMode.Append, FileAccess.Write);
- fsWriter.Write(copy.buffer, 0, copy.buffer.Length);
- fsWriter.Close();
- //当前文件流位置
- lock (copy.stream)
- {
- copy.position += readedLength;
- position += readedLength;
- }
- //响应进度条
- MethodInvoker m = new MethodInvoker(SynchProgressBar);
- m.BeginInvoke(null, null);
- //读取完毕
- if (copy.position >= copy.Size)
- {
- //关闭文件流
- copy.stream.Close();
- //删除备份文件
- File.Delete(copy.DstFile + "_upgrade");
- return;
- }
- //继续读取下个缓存
- lock (copy.stream)
- {
- //剩下的文件大小
- int leftSize = copy.Size - copy.position;
- //如果比缓存小,就将缓存大小设置为剩下的文件大小
- if (leftSize < BUFFER_SIZE)
- copy.buffer = new byte[leftSize];
- //继续异步读取
- copy.stream.BeginRead(copy.buffer, 0, copy.buffer.Length, new AsyncCallback(AsyncCopyFile), copy);
- }
- }
- catch (Exception Ex)
- {
- //出错,恢复备份文件
- File.Copy(copy.DstFile + "_upgrade", copy.DstFile, true);
- MessageBox.Show("更新出错" + Ex.ToString());
- }
- }
- public delegate void delegate_SynProgress();
- private void SynchProgressBar()
- {
- if (this.InvokeRequired)
- {
- this.Invoke(new delegate_SynProgress(SynchProgressBar));
- }
- else
- {
- if (position >= totalSize)
- {
- this.Close();
- //下列为复制完毕后的操作,这里是启动复制文件中的第一个文件
- Process p = new Process();
- ProcessStartInfo si = new ProcessStartInfo();
- si.FileName = CopyList[0].DstFile;
- si.WindowStyle = ProcessWindowStyle.Normal;
- //为true,则用默认的打开方式打开,如果是exe等,设置为false
- si.UseShellExecute = false;
- p.StartInfo = si;
- p.Start();
- }
- this.progressBar1.Maximum = totalSize;
- this.progressBar1.Value = position;
- }
- }
配置文件说明
程序的配置文件为config.xml,格式如下:
- <config>
- <update>
- <Path>C:/</Path>
- <Name>1.exe</Name>
- </update>
- <update>
- <Path>D:/</Path>
- <Name>2.rar</Name>
- </update>
- </config>
<Path>填写复制的源路径<Name>是源文件的文件名,<update>节点可以有多个.
小结
程序在复制失败上做了一个备份恢复的功能,没有进行详细的测试,在异步程序中,异常的捕获要在程序块的最里层(这个和线程很相似,否则程序会因为捕获不到异常而出现程序崩溃的情况,就执行不到文件恢复了.),所以我在异步调用的回调方法中些了文件恢复的功能.程序还有很多功能没有考虑,比如,目标文件名不能更改,路径也不能更改等.
- [C#]实现文件复制[更新]实时显示进度条
- C# 文件复制 进度条显示
- Qt 实现文件复制 界面有进度条(根据文件大小)显示复制进度,
- 更新进度条C语言实现
- 文件复制过程中显示进度条(九)
- 复制文件时,如何显示进度条
- 复制文件时,如何显示进度条
- Java复制文件使用进度条显示
- FileInputStream复制文件,实时显示速度
- VC进度条实时显示
- VC进度条实时显示
- Android中通过Handler实现进度条的实时更新
- C实现复制文件
- 利用WinInet和多线程实现实时显示的下载进度条
- 基于Jquery插件Uploadify实现实时显示进度条上传图片
- cgi 上传文件(c 语言) 进度条显示
- cgi 上传文件(c 语言) 进度条显示
- cgi 上传文件(c 语言) 进度条显示
- 【C#】数据导出到Excel
- DB2字符处理函数
- .net form登陆后打开主窗体并关闭登陆窗
- 讲解如何利用NT Native API获取NT系统的CPU使用率(支持多核)
- 【C#】Socket编程
- [C#]实现文件复制[更新]实时显示进度条
- 【asp.net】VS.Net 下的Wondows窗体常用项目
- 关于为对话框添加背景图片LoadBitmap的问题
- 【c#】如何动态加载控件以及插件编程思想
- 【c#】C#中利用DirectX实现声音播放
- 谷歌Chrome不是浏览器
- SQL server 2005中新增函数及操作
- 【C#+ASP.NET】ASP.NET跨页面传值技巧总结
- html:options标签与html:optionCollectoin标签