小文件复制时使用File.Copy()方法非常方便,但在程序中复制大文件系统将处于假死状态(主线程忙于复制大量数据),你也许会说使用多线程就可以解决这个问题了,但是如果文件过大,没有显示复制时的进度就会让用户处于盲目的等待中。下面的示例使用文件流分块形式复制文件解决这个问题,但发现块的大小选择很关键且速度好像还是没有直接使用Windows中自带的复制速度快:

显示源代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Threading;

namespace SimpleDemo
{
    /// <summary>
    /// 大文件复制
    /// </summary>
    public partial class frm16BigFileCopy : Form
    {
        public frm16BigFileCopy()
        {
            InitializeComponent();
        }

private void btnFrom_Click(object sender, EventArgs e)
        {
            //使用打开文件对话框指定要复制的源大文件
            using (OpenFileDialog ofd = new OpenFileDialog())
            {
                if (ofd.ShowDialog() == DialogResult.OK)
                {
                    txtFrom.Text = ofd.FileName;
                }
            }
        }

private void btnTo_Click(object sender, EventArgs e)
        {
            //使用打开文件对话框指定要复制到的目标大文件
            using (OpenFileDialog ofd = new OpenFileDialog())
            {
                if (ofd.ShowDialog() == DialogResult.OK)
                {
                    txtTo.Text = ofd.FileName;
                }
            }
        }

private void btnStart_Click(object sender, EventArgs e)
        {
            progressBar1.Value = 0;
            lblInfo.Text = "0.0%";
            //实例化一个线程,使用Lambda表达式初始化对象
            Thread t = new Thread(() =>
            {
                //单次复制时块的大小,以B为单位
                int sectionSize = 1024 * 200;
                //获得要复制的源文件流
                FileStream from = new FileStream(txtFrom.Text, FileMode.Open, FileAccess.Read);
                //获得要复制的目标文件流,文件模式为添加
                FileStream to = new FileStream(txtTo.Text, FileMode.Append, FileAccess.Write);

//如果源文件长度小于单次复制时块的大小
                //小文件不用多次复制
                if (from.Length > sectionSize)
                {
                    //已复制长度
                    long copied = 0;
                    //当剩下的长度比单次复制时块要小时退出循环
                    while (from.Length - copied >= sectionSize)
                    {
                        //从文件流中把指定长度的字节复制到目录流中
                        CopySection(from, to, sectionSize);
                        //使源文件流的当前位置与目标文件流同步
                        to.Position = from.Position;
                        //累加已复制的长度
                        copied += sectionSize;
                        //计算已复制比率
                        long rate = copied * 100 / from.Length;
                        //将操作交给主线程
                        this.Invoke((MethodInvoker)delegate()
                        {
                            //显示完成进度信息
                            progressBar1.Value = (int)rate;
                            lblInfo.Text = rate.ToString() + "%";
                        });
                    }
                    //计算剩余未复制的字节数
                    int left = Convert.ToInt32(from.Length - copied);
                    //将剩余的最后部分复制完成
                    CopySection(from, to, left);
                }
                else
                {
                    //从文件流中把指定长度的字节复制到目录流中
                    CopySection(from, to, (int)from.Length);
                }
                from.Dispose();
                to.Dispose();
                //将操作交给主线程
                this.Invoke((MethodInvoker)delegate()
                {
                    //显示完成进度信息
                    progressBar1.Value = 100;
                    lblInfo.Text = "100%";
                    MessageBox.Show("复制完成");
                });
            });
            //线程开始运行
            t.Start();
        }

/// <summary>
        /// 从文件流中把指定长度的字节复制到目录流中
        /// </summary>
        /// <param name="from">源文件流</param>
        /// <param name="to">目标文件流</param>
        /// <param name="len">要复制的长度</param>
        private static void CopySection(FileStream from, FileStream to, int len)
        {
            //实例化一个临时字节缓冲数组
            byte[] buffer = new byte[len];
            //从源文件流中读取0到len长度的字节到buffer中
            from.Read(buffer, 0, len);
            //清除该流的缓冲区,缓冲的数据都将写入到文件系统
     from.Flush();
            //将0到len长度的字节从buffer中写入到目标文件流中
to.Write(buffer, 0, len);
            //清除该流的缓冲区,缓冲的数据都将写入到文件系统
to.Flush();
}
}
}

问题:我试过单次复制时块的大小sectionSize取值与复制的速度有很大的关系,不知道有那位能告诉我怎样才能计算出每次sectionSize的取值最合理。

当然我还有另外一种想法不过没有用代码实现,就是在复制时使用多个线程同时将一个文件流中数据复制到目标位置去合并,理论上应该可以实现,且会成倍加速,有点类似BT,不知道大家还有没有别的好办法,愿意学习。

转载于:https://www.cnblogs.com/best/archive/2011/08/07/2129896.html

大文件复制时块的取值问题相关推荐

  1. 计算机专业大几用到移动硬盘,大文件复制到移动硬盘的方法

    大文件复制到移动硬盘的方法 大文件如何复制到移动硬盘本文是小编精心编辑的大文件复制到移动硬盘的方法,希望能帮助到你! 大文件复制到移动硬盘的方法篇一 一.网线的选择 在短距离传输中五类.超五类.六类都 ...

  2. java当数值超过byte时_【Java学习重难点记录】byte数据类型在显式类型转换时超出其取值范围的转换过程...

    写在前面 本文章转载于我的个人blog UltraFisher,欢迎大家浏览: https://ultrafisher.github.io 原文链接:https://ultrafisher.githu ...

  3. 如何将大文件复制到U盘?

    当我们把大文件拷贝到U盘上时,有时候即使U盘容量足够大也无法拷贝,这是由于U盘默认文件系统属性为FA32的原因. U盘的文件系统主要有NTFS.FAT16.FAT32三种形式,三种形式对应单个文件的大 ...

  4. 闪存驱动器_为什么不能将大文件复制到高容量闪存驱动器?

    闪存驱动器 You have a brand new high-capacity flash drive that can store more than the hard drive of your ...

  5. DiskFileUpload + BeanUtils 轻松实现无框架文件上传表单取值

    文件上传中form表单的enctype="multipart/form-data"  为二进制文件传输 在struts2中 表单取值比较简单  因为框架已经帮我们做好的表单域的取值 ...

  6. 当集合a为空集时a的取值范围_1.2 集合间的基本关系20202021学年高一数学新教材配套学案(人教A版必修第一册)...

    1.2 集合间的基本关系 [学习目标] 课程标准 学科素养 1. 理解子集.真子集.空集的概念:(重点) 2. 能用符号和Venn图表示集合间的关系:(难点) 3. 掌握列举有限集的所有子集的方法. ...

  7. 不等式大两边小中间_不等式取值范围口诀

    不等式取值范围口诀2019-09-27 11:13:46文/宋则贤 不等式就是用大于,小于,大于等于,小于等于连接而成的数学式子.不等式取值范围口诀为同大取大,同小取小.大大小小没有解,大小小大取中间 ...

  8. notepad++打开大文件/复制大量数据卡死的解决方法

    问题描述 首先复制了大量数据,然后在notepad++新建标签,将数据粘贴进去发现notepad++卡死了,重启之后还是卡死. 所以尝试新建文本文档,再右键该文件用notepad++打开,这时候发现n ...

  9. [mybatis]映射文件_参数处理_#取值时指定参数相关规则

    jdbcType通常需要在某种特定的条件下被设置: 在我们数据为null的时候,有些数据库可能不能识别mybatis对null的默认处理.比如Oracle(报错): jdbcType OTHER:无效 ...

  10. python csv文件复制时的编码问题_使用python读取CSV文件时的编码问题

    尝试使用python读取CSV文件时遇到障碍. 更新:如果只想跳过字符或错误,可以打开文件,如下所示: with open(os.path.join(directory, file), 'r', en ...

最新文章

  1. Python使用numpy中的hstack函数水平堆叠(horizontally stack)数组实战
  2. 学习css3的弹性盒模型
  3. Android安全研究经验谈
  4. 小程序bindtap参数传递
  5. “新基建”沙龙(一)精华回顾 | 5G与工业互联网的发展机遇与挑战
  6. HDU2602 (0-1背包)
  7. 为Spring Cloud Ribbon配置请求重试(Camden.SR2+)
  8. ubuntu mysql双主热备配置_MySql双主热备配置
  9. springboot maven项目打jar包
  10. 面试题之synchronized与Lock的区别
  11. 使用Python批量下载哨兵1号数据
  12. 项目管理过程组-十五至尊图
  13. monkey命令——压力测试——转载参考01
  14. 可视化界面 Sentinel 流控卫兵 限流 熔断 系统保护
  15. 7.5W10W无线充电解决方案原理图
  16. 如何克服学习过程中的焦虑?
  17. SAP中使用BDC创建或修改采购信息记录
  18. iOS-自定义键盘选择器
  19. 2016012056+陈逸璇+散列函数的应用及其安全性
  20. 计算机画图怎样更改文字,如何使用最简单的画图工具修改图片或者文字

热门文章

  1. Python3—元组
  2. maven工程的多环境配置方案(profile)
  3. 2017-2018-1 20155315 《信息安全系统设计基础》第11周学习总结
  4. Xpath定位方法深入探讨及元素定位失败常见情况
  5. 深入理解Core Data
  6. FCC算法题--Validate US Telephone Numbers
  7. 手把手教你配置苹果APNS推送服务|钿畑的博客 | 钿畑的博客
  8. 转载--#define 用法
  9. C++ Primer 第八章 标准IO库(转载)
  10. Android PM suspendresume