.NET实现多线程拷贝文件

一、帮助类

using System;
using System.IO;
using System.Threading;
using Microsoft.Win32.SafeHandles;
using System.Runtime.InteropServices;
using System.Diagnostics;namespace FastCopyClass
{public class FastCopy{private const short FILE_ATTRIBUTE_NORMAL = 0x80;private const short INVALID_HANDLE_VALUE = -1;private const uint GENERIC_READ = 0x80000000;private const uint GENERIC_WRITE = 0x40000000;private const uint CREATE_NEW = 1;private const uint CREATE_ALWAYS = 2;private const uint OPEN_EXISTING = 3;private const uint FILE_FLAG_NO_BUFFERING = 0x20000000;private const uint FILE_FLAG_WRITE_THROUGH = 0x80000000;private const uint FILE_SHARE_READ = 0x00000001;private const uint FILE_SHARE_WRITE = 0x00000002;[DllImport("kernel32.dll", SetLastError = true)]static extern SafeFileHandle CreateFile(string IpFileName, uint dwDesiredAccess,uint dwShareMode, IntPtr IpSecurityAttributes, uint dwCreationDisposition,uint dwFlagsAndAttributes, IntPtr hTemplateFile);private int _ThreadNum;private Thread[] CopyThread;private long ReadBufferSize = 1024 * 1024 * 16;public long TotalReadCount = 0;public long AverageCopySpeed;public int ProgressBarValue = 0;private DateTime start;private FileInfo SourceFileInfo;private string _DestFileName;private string _SourceFileName;private bool _IsUsingSystemBuff;public delegate void CopyFinished(string IsFinish);private bool[] isfirst;public event CopyFinished CopyF;private bool WaitingEnd = true;private DateTime WaitTime;private int ThreadExitCout = 0;private object ThreadLock = new object();/// <summary>/// 执行复制函数,线程数如果大于8将按照最多8线程复制/// </summary>/// <param name="SourceFileName">源文件全路径</param>/// <param name="DestFileName">目标文件全路径</param>/// <param name="IsUsingSystemBuff">是否使用系统缓存,不使用系统缓存的复制速度将远大于使用系统缓存的复制速度</param>/// <param name="ThreadNum">复制线程数</param>/// <param name="IsSynchronous">true是同步,false是异步</param>/// <param name="WaitMilliseconds">同步等待时间</param>public void ExeCopy(string SourceFileName, string DestFileName, bool IsUsingSystemBuff, int ThreadNum, bool IsSynchronous, double WaitMilliseconds){//Console.WriteLine("开始时间:" + DateTime.Now.ToString("hh:mm:ss"));try{SourceFileInfo = new FileInfo(SourceFileName);_DestFileName = DestFileName;_SourceFileName = SourceFileName;_IsUsingSystemBuff = IsUsingSystemBuff;//if (SourceFileInfo.Exists)//{//小文件使用系统复制File.Copyif (SourceFileInfo.Length > 0 && SourceFileInfo.Length < 100 * 1024 * 1024){File.Copy(SourceFileName, DestFileName,true);}else//大于100M文件才使用FastCopy{if (ThreadNum > 0){//建立于源文件同样大小的目标空文件if (initFile(SourceFileName, DestFileName))//如果建立或者覆盖文件成功{//打开目标文件//线程数量限制ThreadNum = ThreadNum > 8 ? 8 : ThreadNum;_ThreadNum = ThreadNum;CopyThread = new Thread[ThreadNum];isfirst = new bool[ThreadNum];if (ThreadNum == 1)//执行单线程复制{ThreadParams threadParam = new ThreadParams();threadParam.StartPosition = 0;threadParam.ReadLength = SourceFileInfo.Length;threadParam.start = DateTime.Now;CopyThread[0] = new Thread(new ParameterizedThreadStart(ExeThreadCopy));CopyThread[0].Start(threadParam);}else//执行多线程复制{long parts = (long)_ThreadNum;long StartPosition = 0;long len = SourceFileInfo.Length;long last = SourceFileInfo.Length % parts;len = len - last;long PartLength = len / parts;PartLength = PartLength - PartLength % 512;last = SourceFileInfo.Length - parts * PartLength;start = DateTime.Now;//记录开始时间for (int i = 0; i < ThreadNum; i++){CopyThread[i] = new Thread(new ParameterizedThreadStart(ExeThreadCopy));CopyThread[i].Name = i.ToString();if (i == ThreadNum - 1){ThreadParams threadParam = new ThreadParams();threadParam.StartPosition = StartPosition;threadParam.ReadLength = PartLength + last;threadParam.start = start;CopyThread[i].Start(threadParam);}else{ThreadParams threadParam = new ThreadParams();threadParam.StartPosition = StartPosition;threadParam.ReadLength = PartLength;StartPosition += PartLength;threadParam.start = start;CopyThread[i].Start(threadParam);}}}}}elsethrow new Exception("线程数不能小于1");}//}//else//    throw new Exception("打开源文件失败!");//等待线程结束if (IsSynchronous){WaitTime = DateTime.Now;WaitForEnd(WaitMilliseconds);}}catch (Exception ex){PubLibrary.WriteErrLog(ex.ToString());throw ex;}//Console.WriteLine("结束时间:" + DateTime.Now.ToString("hh:mm:ss"));}private void WaitForEnd(double WaitMilliseconds){while (ThreadExitCout < _ThreadNum){Thread.Sleep(100);TimeSpan ts = DateTime.Now.Subtract(WaitTime);if (ts.TotalMilliseconds > WaitMilliseconds){throw new Exception("文件拷贝超时异常");break;}}}private bool initFile(string SourceFileName, string DestFileName){try{FileInfo SourceFileInfo = new FileInfo(SourceFileName);FileInfo DestFileInfo = new FileInfo(DestFileName);if (DestFileInfo.Exists){DestFileInfo.Delete();}Process p = new Process();p.StartInfo.FileName = "fsutil";p.StartInfo.Arguments = "file createnew " + DestFileName + " " + SourceFileInfo.Length.ToString();p.StartInfo.UseShellExecute = false;p.StartInfo.RedirectStandardOutput = true;p.StartInfo.RedirectStandardError = true;p.StartInfo.CreateNoWindow = true;p.Start();p.WaitForExit(1000 * 60 * 2);return true;}catch (Exception ex){PubLibrary.WriteErrLog(ex.ToString());throw ex;}}private void ExeThreadCopy(object obj){ThreadParams param = (ThreadParams)obj;SafeFileHandle SafeFile_SourceFile = CreateFile(_SourceFileName, GENERIC_READ, FILE_SHARE_READ, IntPtr.Zero,OPEN_EXISTING, _IsUsingSystemBuff ? 0 : FILE_FLAG_NO_BUFFERING, IntPtr.Zero);SafeFileHandle SafeFile_DestFile = CreateFile(_DestFileName, GENERIC_WRITE, FILE_SHARE_WRITE, IntPtr.Zero,OPEN_EXISTING, _IsUsingSystemBuff ? 0 : (FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH), IntPtr.Zero);FileStream SourceFileStream = new FileStream(SafeFile_SourceFile, FileAccess.Read);FileStream DestFileStream = new FileStream(SafeFile_DestFile, FileAccess.Write);if (param.StartPosition != 0){SourceFileStream.Seek(param.StartPosition, SeekOrigin.Begin);DestFileStream.Seek(param.StartPosition, SeekOrigin.Begin);}BinaryReader SourceFileReader = new BinaryReader(SourceFileStream);BinaryWriter DestFileWriter = new BinaryWriter(DestFileStream);long ThreadTotalReadCount = 0;long ThreadOneTimeReadCount = 0;long ReadCount = 0;bool IsEndPart = false;byte[] ReadBuff = new byte[ReadBufferSize];int ThreadName = int.Parse(Thread.CurrentThread.Name);while (ThreadTotalReadCount < param.ReadLength){//计算每次应该读取流的长度,因为在每部分的最后一点不一定是ReadBufferSize大小?如果不设置流的读取长度,有可能在每部分最后一次读取越界。读到下一部分的内容。Console.WriteLine(Thread.CurrentThread.Name);ReadCount = param.ReadLength - ThreadTotalReadCount < ReadBufferSize ? param.ReadLength - ThreadTotalReadCount : ReadBufferSize;if (ReadCount % 512 == 0)//不是最后一部分的最后一点{IsEndPart = false;}else{IsEndPart = true;}if (IsEndPart){FileStream SourceFileLastStream = new FileStream(_SourceFileName, FileMode.Open, FileAccess.Read, FileShare.Read);FileStream DestFileLastStream = new FileStream(_DestFileName, FileMode.Open, FileAccess.Write, FileShare.Write);BinaryReader SourceFileReadLast = new BinaryReader(SourceFileLastStream);BinaryWriter DestFileWriteLast = new BinaryWriter(DestFileLastStream);SourceFileLastStream.Seek(SourceFileStream.Position, SeekOrigin.Begin);DestFileLastStream.Seek(DestFileStream.Position, SeekOrigin.Begin);byte[] LastBuff = new byte[ReadCount];ThreadOneTimeReadCount = SourceFileReadLast.Read(LastBuff, 0, (int)ReadCount);DestFileWriteLast.Write(LastBuff, 0, (int)ReadCount);try{SourceFileReadLast.Close();}catch { }try{DestFileWriteLast.Close();}catch { }try{SourceFileLastStream.Close();}catch { }try{DestFileLastStream.Close();}catch { }if (CopyF != null){CopyF("复制完成");}}else{ThreadOneTimeReadCount = SourceFileReader.Read(ReadBuff, 0, (int)ReadCount);DestFileWriter.Write(ReadBuff, 0, (int)ReadCount);}TotalReadCount += ThreadOneTimeReadCount;ThreadTotalReadCount += ThreadOneTimeReadCount;TimeSpan ts = DateTime.Now.Subtract(param.start);AverageCopySpeed = TotalReadCount / (long)ts.TotalMilliseconds * 1000 / (1024 * 1024);ProgressBarValue = (int)(TotalReadCount * 100 / SourceFileInfo.Length);WaitTime = DateTime.Now;}try{SourceFileReader.Close();}catch { };try{DestFileWriter.Close();}catch { };try{SourceFileStream.Close();}catch { };try{DestFileStream.Close();}catch { };try{SafeFile_SourceFile.Close();}catch { };try{SafeFile_DestFile.Close();}catch { };lock (ThreadLock){ThreadExitCout += 1;}}private void ExcNormalCopy(object obj){ThreadParams param = (ThreadParams)obj;FileStream SourceFileStream = new FileStream(_SourceFileName, FileMode.Open, FileAccess.Read, FileShare.Read);FileStream DestFileStream = new FileStream(_DestFileName, FileMode.Open, FileAccess.Write, FileShare.Write);BinaryReader SourceFileReader = new BinaryReader(SourceFileStream);BinaryWriter DestFileWriter = new BinaryWriter(DestFileStream);SourceFileStream.Seek(param.StartPosition, SeekOrigin.Begin);DestFileStream.Seek(param.StartPosition, SeekOrigin.Begin);long ThreadTotalReadCount = 0;long ThreadOneTimeReadCount = 0;long ReadCount = 0;byte[] buff = new byte[ReadBufferSize];while (TotalReadCount < param.ReadLength){ReadCount = param.ReadLength - ThreadTotalReadCount >= ReadBufferSize ? ReadBufferSize : param.ReadLength - ThreadTotalReadCount;ThreadOneTimeReadCount = SourceFileReader.Read(buff, 0, (int)ReadCount);DestFileWriter.Write(buff, 0, (int)ReadCount);TimeSpan ts = DateTime.Now.Subtract(param.start);TotalReadCount += ThreadOneTimeReadCount;ThreadTotalReadCount += ThreadOneTimeReadCount;AverageCopySpeed = TotalReadCount / (long)ts.TotalMilliseconds * 1000 / (1024 * 1024);ProgressBarValue = (int)(TotalReadCount * 100 / SourceFileInfo.Length);}SourceFileReader.Close();DestFileWriter.Close();SourceFileStream.Close();DestFileStream.Close();}public void AbortAllThread(){for (int i = 0; i < _ThreadNum; i++){if (CopyThread[i].IsAlive){CopyThread[i].Abort();}}}}public class ThreadParams{public long StartPosition;public long ReadLength;public DateTime start;}
}

二、使用

using System;
using FastCopyClass;namespace FileUploadClass
{public class FileUpload{private static FastCopy fc = new FastCopy();/// <summary>/// 复制文件夹及文件/// </summary>/// <param name="sourceFolder">原文件路径</param>/// <param name="destFolder">目标文件路径</param>/// <returns></returns>public static bool CopyFolder(string sourceFolder, string destFolder){try{PubLibrary.WriteErrLog("复制文件开始:" + DateTime.Now.ToString("yyyy-MM/dd HH:mm:ss"));string folderName = System.IO.Path.GetFileName(sourceFolder);string destfolderdir = System.IO.Path.Combine(destFolder, folderName);string[] filenames = System.IO.Directory.GetFileSystemEntries(sourceFolder);foreach (string file in filenames)// 遍历所有的文件和目录{if (System.IO.Directory.Exists(file)){string currentdir = System.IO.Path.Combine(destfolderdir, System.IO.Path.GetFileName(file));if (!System.IO.Directory.Exists(currentdir)){System.IO.Directory.CreateDirectory(currentdir);}CopyFolder(file, destfolderdir);}else{string srcfileName = System.IO.Path.Combine(destfolderdir, System.IO.Path.GetFileName(file));if (!System.IO.Directory.Exists(destfolderdir)){System.IO.Directory.CreateDirectory(destfolderdir);}fc.ExeCopy(file,srcfileName,false,8,false,30 * 60 * 60 * 1000);//System.IO.File.Copy(file, srcfileName,true);}}PubLibrary.WriteErrLog("复制文件结束:" + DateTime.Now.ToString("yyyy-MM/dd HH:mm:ss"));return true;}catch (Exception ex){PubLibrary.WriteErrLog("复制粘贴文件夹:" + ex.ToString());return false;}}}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/141810.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

华为云云耀云服务器L实例评测 | 云服务器搭建自己的gitlab代码仓库手把手教学

&#x1f4cb; 前言 &#x1f5b1; 博客主页&#xff1a;在下马农的碎碎念&#x1f917; 欢迎关注&#x1f50e;点赞&#x1f44d;收藏⭐️留言&#x1f4dd;✍ 本文由在下马农原创&#xff0c;首发于CSDN&#x1f4c6; 首发时间&#xff1a;2023/09/26&#x1f4c5; 最近更新时…

【STM32单片机】u8g2智能风扇设计

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用STM32F103C8T6单片机控制器&#xff0c;使用按键、IIC OLED模块、DS18B20温度传感器、直流电机、红外遥控等。 主要功能&#xff1a; 初始化后进入温度显示界面&#xff0c;系统初始状态为手动…

医院陪诊小程序源码 陪诊陪护小程序源码

医院陪诊小程序源码 陪诊陪护小程序源码 近年来&#xff0c;随着互联网技术的不断发展&#xff0c;我们的生活中出现了越来越多的智能设备和智能应用&#xff0c;这些智能应用不仅极大方便了我们的生活&#xff0c;还对现代医疗服务体验产生了深远的影响。本文将为大家介绍一种…

JVM G1垃圾回收器学习笔记

前言 最近在工作中遇到频繁FullGC且YoungGC时间有时特别长的情况&#xff0c;而自己对JVM的垃圾回收也是一知半解&#xff0c;因此需要对JVM做系统的了解&#xff0c;为快速解决工作中的问题&#xff0c;能有效分析GC日志和业务代码&#xff0c;先从G1垃圾回收器开始学习&…

贪心算法-

代码随想录 什么是贪心 贪心的本质是选择每一阶段的局部最优&#xff0c;从而达到全局最优。 这么说有点抽象&#xff0c;来举一个例子&#xff1a; 例如&#xff0c;有一堆钞票&#xff0c;你可以拿走十张&#xff0c;如果想达到最大的金额&#xff0c;你要怎么拿&#xff…

linux驱动之input子系统简述

文章目录 一、什么是input子系统二、内核代码三、代码分析 一、什么是input子系统 Input驱动程序是linux输入设备的驱动程序&#xff0c;我们最常见的就按键&#xff0c;触摸&#xff0c;插拔耳机这些。其中事件设备驱动程序是目前通用的驱动程序&#xff0c;可支持键盘、鼠标…

邮件营销方案

互联网的快速发展&#xff0c;使得新媒体营销、短视频营销、微信营销等新型营销方式成为主流。但是邮件营销仍然是性价比很高的营销方式之一&#xff0c;它不仅可以帮助你与潜在客户建立联系、传达信息并促进销售&#xff0c;同时也是维系老客户的重要手段之一。特别是对于外贸…

解答嵌入式和单片机的关系

嵌入式系统是一种特殊的计算机系统&#xff0c;用于特定任务或功能。而单片机则是嵌入式系统的核心部件之一&#xff0c;是一种在单个芯片上集成了处理器、内存、输入输出接口等功能的微控制器。刚刚好我这里有一套单片机保姆式教学&#xff0c;里面有编程教学、问题讲解、语言…

C++:优先级队列模拟实现和仿函数的概念使用

文章目录 使用方法Compare仿函数一些场景模板参数和函数参数 本篇总结优先级队列 使用方法 首先在官网查看它的一些用法 template <class T, class Container vector<T>,class Compare less<typename Container::value_type> > class priority_queue;从…

【golang】深入理解Go语言垃圾回收(GC)

垃圾回收 垃圾回收版本1.3之前标记-清除&#xff08;mark and sweep&#xff09;算法标记-清除&#xff08;mark and sweep&#xff09;的缺点 版本1.5的三色并发标记法没有STW的三色标记法屏障机制强-弱 三色不等式插入屏障删除屏障 版本1.8的混合写屏障&#xff08;hybrid wr…

【计算机网络】——数据链路层(应用:局域网、广域网、设备 )

//仅做个人复习和技术交流&#xff0c;图片取自王道考研&#xff0c;侵删 一、大纲 1、介质访问控制 信道划分介质访问控制 随机访问介质访问控制 2、局域网 3、广域网 4、数据链路层设备 二、局域网 1、局域网基本概念和体系结构 局域网(LocalArea Network): 简称LAN&…

[maven] 实现使用 plugin 及 properties 简述

[maven] 实现&使用 plugin 及 properties 简述 这章内容&#xff0c;我个人感觉可看可不看……&#xff1f; 不过课都上了&#xff0c;笔记 &#x1f4d2; 补完才对得起自己嘛 plugins 主要讲一下 maven 的 plugin 时怎么实现的&#xff0c;以及项目中怎么调用自己实现…

实现电商跨平台订单每日自动对账

场景描述&#xff1a; 多数商家都存在多电商平台同时经营的情况&#xff0c;而进行订单对账则是相关业务或财务人员的每日必修课。比如商家在天猫&#xff0c;苏宁&#xff0c;1号店&#xff0c;京东等均有运营店铺&#xff0c;每天需要通过各电商后台系统抓单打单&#xff0c…

若依cloud -【 100 ~ 103 】

100 分布式日志介绍 | RuoYi 分布式日志就相当于把日志存储在不同的设备上面。比如若依项目中有ruoyi-modules-file、ruoyi-modules-gen、ruoyi-modules-job、ruoyi-modules-system四个应用&#xff0c;每个应用都部署在单独的一台机器里边&#xff0c;应用对应的日志的也单独存…

springboot如何接入netty,实现在线统计人数?

springboot如何接入netty&#xff0c;实现在线统计人数&#xff1f; Netty 是 一个异步事件驱动的网络应用程序框架 &#xff0c;用于快速开发可维护的高性能协议服务器和客户端。 Netty ​ 是一个 NIO 客户端服务器框架 ​&#xff0c;可以快速轻松地开发协议服务器和客户端等…

微表情识别API + c++并发服务器系统

微表情识别API c并发服务器系统 该项目只开源c并发服务器程序&#xff0c;模型API部分不开源 地址&#xff1a;https://github.com/lin-lai/-API- 更新功能 4.1版本 改用epoll实现IO多路复用并发服务器 项目介绍 本项目用于检测并识别视频中人脸的微表情 目标任务: 用户上…

【李沐深度学习笔记】线性代数

课程地址和说明 线性代数p1 本系列文章是我学习李沐老师深度学习系列课程的学习笔记&#xff0c;可能会对李沐老师上课没讲到的进行补充。 线性代数 标量 标量&#xff08;scalar&#xff09;&#xff0c;亦称“无向量”。有些物理量&#xff0c;只具有数值大小&#xff0c…

基于微信小程序的校园失物招领系统设计与实现(源码+lw+部署文档+讲解等)

前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌&#x1f497; &#x1f447;&#x1f3fb;…

Qt创建线程(使用moveToThread方法创建子线程)

1.moveTothread方法: &#xff08;1&#xff09;要使用moveToThread方法必须继承与QObject类 &#xff08;2&#xff09;创建任务对象时不能指定父对象 例子&#xff1a; MyWork* work new MyWork(this); // error MyWork* work new MyWork; // ok &#xff08;3&#…

北工大汇编题——分支程序设计

题目要求 信息检素程序设计&#xff1a;在数据区&#xff0c;有9个不同的信息&#xff0c;编号 0-8&#xff0c;每个信息包括20 个字符。从键盘接收 0-8 之间的一个编号&#xff0c;然后再屏幕上显示出相应编号的信息内容&#xff0c;按“q”键退出 完整代码 DATAS SEGMENTn0…