.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.xdnf.cn/news/141939.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

02 MIT线性代数-矩阵消元 Elimination with matrices

一, 消元法 Method of Elimination 消元法是计算机软件求解线形方程组所用的最常见的方法。任何情况下&#xff0c;只要是矩阵A可逆&#xff0c;均可以通过消元法求得Axb的解 eg: 我们将矩阵左上角的1称之为“主元一”&#xff08;the first pivot&#xff09;&#xff0c;第…

【springboot3.x 记录】关于Jakarta包无法引入的问题

最近想将一些项目升级到springboot3.x和java17的时候&#xff0c;发现项目依赖中有Jakarta的包&#xff0c;但是代码标红提示没有相关的类&#xff0c;特此记录一下排查问题和最终解决问题的思路方法 一、发现问题 因为之前有创建过 springboot3.x java17 的项目&#xff0c;…

第6讲:v-for使用

目录 1.循环遍历 2.v-for遍历整形变量&#xff08;99乘法表&#xff09; 3.v-for遍历普通数组 4.v-for遍历数组对象 1.循环遍历 v-for指令基于一个数组渲染一个列表&#xff0c;它和JavaScript的遍历语法相似&#xff1a; v-for”item in list” list 是一个数组&#xff0c; i…

指针笔试题讲解

文章目录 题目答案与解析1、234、5、6、7、8、 题目 int main() {int a[5] { 1, 2, 3, 4, 5 };int *ptr (int *)(&a 1);printf( "%d,%d", *(a 1), *(ptr - 1));return 0; }//由于还没学习结构体&#xff0c;这里告知结构体的大小是20个字节 //由于还没学习结…

2023-09-25 LeetCode每日一题(LFU 缓存)

2023-09-25每日一题 一、题目编号 460. LFU 缓存二、题目链接 点击跳转到题目位置 三、题目描述 请你为 最不经常使用&#xff08;LFU&#xff09;缓存算法设计并实现数据结构。 实现 LFUCache 类&#xff1a; LFUCache(int capacity) - 用数据结构的容量 capacity 初始…

腾讯mini项目-【指标监控服务重构】2023-08-25

今日已办 traefik proxy jaeger Prometheus prometheus | Prometheus 配置完依然无法实现 web-url的前缀访问【待解决】 Set span storage type : elasticsearch services:elasticsearch:image: elasticsearch:7.17.12container_name: elasticsearchnetworks:- backend # …

2023.9.23 关于 HTTP 详解

目录 HTTP 协议 认识 URL HTTP 请求 认识方法 HTTP 响应 认识状态码 总结 HTTP 请求的构造 Form 表单构造 AJAX 构造 Postman 构造 HTTP 协议 应用层使用最广泛的协议浏览器 基于 HTTP协议 获取网站是 浏览器 和 服务器 之间的交互桥梁HTTP协议 基于传输层的 TCP协…

软件测试之Web安全测试详解

前言 随着互联网时代的蓬勃发展&#xff0c;基于Web环境下的应用系统、应用软件也得到了越来越广泛的使用。 目前&#xff0c;很多企业的业务发展都依赖于互联网&#xff0c;比如&#xff0c;网上银行、网络购物、网络游戏等。但&#xff0c;由于很多恶意攻击者想通过截获他人…

Visual Studio 2017 安装

C自学精简实践教程 目录(必读) 这篇文章会保证你第一次安装VS2017就成功运行Hello World! 下载Visual Studio Installer Gitee 下载 VS2017/vs2017_Community.exe CalmReason/VisualStudio - 码云 - 开源中国 (gitee.com) 百度云下载 链接&#xff1a;https://pan.baidu…

【ROS入门】使用 ROS 服务(Service)机制实现同步请求与答复

文章结构 任务要求话题模型实现步骤自定义srv定义srv文件编辑配置文件编译 自定义srv调用vscode配置编写服务端实现编写客户端实现 执行启动roscore编译启动客户端和服务端编译启动roscore启动节点 任务要求 编写代码实现 ROS 中的服务请求与答复: 创建服务端&#xff0c;注册…

YZ09: VBA_Excel之读心术

【分享成果&#xff0c;随喜正能量】多要求自己&#xff0c;你会更加独立&#xff0c;少要求别人&#xff0c;你会减少失望&#xff0c;宁愿花时间去修炼 不完美的自己&#xff0c;也不要浪费时间去期待完美的别人&#xff01;。 我给VBA下的定义&#xff1a;VBA是个人小型自动…

uni-app:实现元素中实现竖直居中

效果展示 前&#xff1a; 后&#xff1a; 未实现前代码 <template><view class"container"><view class"centered-element">我是要被居中的元素</view></view> </template><script>export default {data() {r…

56块钱搭建一个ubuntu 2204 linux 服务器

硬件pdd上淘的一个linux小盒子 应该是以前的机顶盒之类的 实物图如下 今天刚收到小盒子 找了个显示器 键盘 查到小盒子上通电 本来指示灯应该亮的 老板刷机之后 led灯都不亮了 不知道有没有开机 我还以为坏了 刚开始 然后直接连到显示器上 有输出 那说明没问题…

MySQL-树型结构数据查询

表结构 进行树形结构查询&#xff0c;利用特殊语法进行操作 with recursive t as(select parent_id , business_namefrom business_line where id 21union allselect a.parent_id, a.business_namefrom business_line a join t on a.id t.parent_id) select business_name f…

OpenCV两张图片实现稀疏点云的生成

1 E矩阵 1.1 由F到E E K T ∗ F ∗ K E K^T * F * K EKT∗F∗K E 矩阵可以直接通过之前算好的 F 矩阵与相机内参 K 矩阵获得 Mat E K.t() * F * K;相机内参获得的方式是一个较为复杂的方式&#xff0c;需要使用棋盘进行定位获得&#xff0c;我们这里直接使用了 OpenMVG 提…

网络编程-UDP协议(发送数据和接收数据)

需要了解TCP协议的&#xff0c;可以看往期文章 https://blog.csdn.net/weixin_43860634/article/details/133274701 TCP/IP参考模型 通过此图&#xff0c;可以了解UDP所在哪一层级中 代码案例 发送数据 package com.hidata.devops.paas.udp;import java.io.IOException; …

HTML+CSS综合案例二:CSS简介

<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title> CSS简介</title><style>h1{color: #33…

Learn Prompt- Midjourney 图片生成:Image Prompts

Prompt 自动生成 前不久&#xff0c;Midjourney 宣布支持图片转 prompt 功能。 原始图片​ blueprint holographic design of futuristic Midlibrary --v 5Prompt 生成​ 直接输入 /describe 指令通过弹出窗口上传图像并发送&#xff0c;Midjourney 会根据该图像生成四种可…

机器学习小白理解之一元线性回归

关于机器学习&#xff0c;百度上一搜一大摞&#xff0c;总之各有各的优劣&#xff0c;有的非常专业&#xff0c;有的看的似懂非懂。我作为一名机器学习的门外汉&#xff0c;为了看懂这些公式和名词真的花了不少时间&#xff0c;还因此去着重学了高数。 不过如果不去看公式&…

渗透测试信息收集方法和工具分享

文章目录 一、域名收集1.OneForAll2.子域名挖掘机3.subdomainsBurte4.ssl证书查询 二、获取真实ip1.17CE2.站长之家ping检测3.如何寻找真实IP4.纯真ip数据库工具5.c段&#xff0c;旁站查询 三、端口扫描1.端口扫描站长工具2.masscan(全端口扫描)nmap扫描3.scanport4.端口表5.利…