首页 > 编程语言 >C# 文件同步工具(复制带进度显示)

C# 文件同步工具(复制带进度显示)

时间:2022-11-12 22:46:00浏览次数:37  
标签:文件 file Console string C# Write 复制 进度 WriteLine

using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;

namespace SyncTool
{
    internal class Program
    {
        private static string oldPath = @"";
        private static string newPath = @"";
        static void Main(string[] args)
        {

            if (args.Length == 2)
            {
                oldPath = args[0];
                newPath = args[1];
            }

        GoJob:
            Console.WriteLine("---------------------------------------------");
            Console.WriteLine("------------------文件同步工具---------------");
            Console.WriteLine("---------------------------------------------");

            while (!Directory.Exists(oldPath))
            {
                Console.WriteLine("请输入源始目录");
                oldPath = Console.ReadLine();
            }

            while (!Directory.Exists(newPath))
            {
                Console.WriteLine("请输入目标目录");
                newPath = Console.ReadLine();
            }

            Console.WriteLine("源始目录:" + oldPath);
            Console.WriteLine("目标目录:" + newPath);
            Console.WriteLine("---------------------------------------------");
            Console.WriteLine("请选择你要执行的操作");
            Console.WriteLine("1:开始同步");
            Console.WriteLine("2:检查文件");
            Console.WriteLine("3:更换目录");
            Console.WriteLine("4:清理屏幕");
            Console.WriteLine("5:退出程序");
            Console.WriteLine("---------------------------------------------");
            string key = Console.ReadLine();

            Console.Write("\n你按下的是:" + key + "\r\n");

            if (key == "1")//查询检测
            {
                CopyFile(oldPath);
                Console.WriteLine("----------------------同步完成-----------------------");
                WriteLog("本次复制失败共有:" + errCopyFileList.Count + "个文件\r\n" + string.Join("\r\n", errCopyFileList.ToArray()));
                Console.WriteLine("---------------------------------------------");

                goto GoJob;
            }
            else if (key == "2")//查询检测
            {
                ExistsFile(oldPath);
                Console.WriteLine("----------------------检测完成-----------------------");
                WriteLog("本次检测不存在文件共有:" + noExistsList.Count + "个文件\r\n" + string.Join("\r\n", noExistsList.ToArray()));
                Console.WriteLine("---------------------------------------------");
                WriteLog("本次检测大小不一的文件共有:" + sizeExistsList.Count + "个文件\r\n" + string.Join("\r\n", sizeExistsList.ToArray()));
                Console.WriteLine("---------------------------------------------");
                goto GoJob;
            }
            else if (key == "3")//
            {
                oldPath = "";
                newPath = "";
                goto GoJob;
            }
            else if (key == "4")//
            {
                Console.Clear();
                goto GoJob;
            }
            else if (key == "5")//
            {
                Environment.Exit(0);
                return;
            }

            else
            {
                Console.WriteLine("\n请输入一个有效键!");
                Console.WriteLine("---------------------------------------------");
                goto GoJob;
            }
        }


        #region 归类循环复制文件
        /// <summary>
        /// 复制失败文件
        /// </summary>
        public static List<string> errCopyFileList = new List<string>();

        /// <summary>
        /// 归类循环复制文件
        /// </summary>
        /// <param name="dir"></param>
        public static void CopyFile(string dir)
        {
            if (string.IsNullOrWhiteSpace(dir)) return;
            if (!Directory.Exists(dir)) return;

            foreach (var file in Directory.GetFiles(dir))
            {
                Console.Write(file);
                string newfile = file.Replace(oldPath, newPath);//文件新地址
                string newdir = Path.GetDirectoryName(newfile);
                if (!Directory.Exists(newdir)) Directory.CreateDirectory(newdir);

                FileInfo oldInfo = new FileInfo(file);//旧文件信息
                FileInfo newInfo = new FileInfo(newfile);//新文件信息

                if (!newInfo.Exists)//新文件不存在
                {
                    Console.Write(" 不存在,复制 ");
                    try
                    {
                        CopyFileEx(file, newfile, new CopyProgressRoutine((total, transferred, streamSize, StreamByteTrans, dwStreamNumber, reason, hSourceFile, hDestinationFile, lpData) =>
                        {
                            double percent = Convert.ToDouble(transferred) / Convert.ToDouble(total);
                            string result = percent.ToString("P");//得到6%
                            Console.Write(result);

                            for (int i = 0; i < result.Length; i++)
                            {
                                Console.Write('\u0008');//删除输出的内容
                            }

                            return CopyProgressResult.PROGRESS_CONTINUE;
                        }), IntPtr.Zero, ref pbCancel, CopyFileFlags.COPY_FILE_RESTARTABLE);

                        Console.Write(" 成功   ");
                    }
                    catch (Exception ex)
                    {
                        if (!errCopyFileList.Contains(file))
                        {
                            errCopyFileList.Add(file);
                        }
                        Console.Write("失败:" + ex.Message);
                    }
                }
                else//新目录存在文件则比对大小
                {
                    Console.Write(" 存在,比大小 ");
                    if (oldInfo.Length != newInfo.Length)//旧目录大小和新目录大小不一样
                    {
                        Console.Write(" " + oldInfo.Length + "-->" + newInfo.Length + " 大小不一,复制 ");
                        try
                        {
                            CopyFileEx(file, newfile, new CopyProgressRoutine((total, transferred, streamSize, StreamByteTrans, dwStreamNumber, reason, hSourceFile, hDestinationFile, lpData) =>
                            {
                                double percent = Convert.ToDouble(transferred) / Convert.ToDouble(total);
                                string result = percent.ToString("P");//得到6%
                                Console.Write(result);

                                for (int i = 0; i < result.Length; i++)
                                {
                                    Console.Write('\u0008');//删除输出的内容
                                }

                                return CopyProgressResult.PROGRESS_CONTINUE;
                            }), IntPtr.Zero, ref pbCancel, CopyFileFlags.COPY_FILE_RESTARTABLE);

                            Console.Write("成功");
                        }
                        catch (Exception ex)
                        {
                            if (!errCopyFileList.Contains(file))
                            {
                                errCopyFileList.Add(file);
                            }
                            Console.Write("失败:" + ex.Message);
                        }
                    }
                    else//大小一致则跳过
                    {
                        Console.Write(" 一致,跳过 ");
                    }
                }
                Console.WriteLine("");
            }

            foreach (var mydir in Directory.GetDirectories(dir))
            {
                CopyFile(mydir);
            }
        }
        #endregion


        #region Win32_API 复制文件带进度
        [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool CopyFileEx(string lpExistingFileName, string lpNewFileName, CopyProgressRoutine lpProgressRoutine, IntPtr lpData, ref Int32 pbCancel, CopyFileFlags dwCopyFlags);

        delegate CopyProgressResult CopyProgressRoutine(long TotalFileSize, long TotalBytesTransferred, long StreamSize, long StreamBytesTransferred, uint dwStreamNumber, CopyProgressCallbackReason dwCallbackReason, IntPtr hSourceFile, IntPtr hDestinationFile, IntPtr lpData);

        private static int pbCancel;

        enum CopyProgressResult : uint
        {
            PROGRESS_CONTINUE = 0,
            PROGRESS_CANCEL = 1,
            PROGRESS_STOP = 2,
            PROGRESS_QUIET = 3
        }

        enum CopyProgressCallbackReason : uint
        {
            CALLBACK_CHUNK_FINISHED = 0x00000000,
            CALLBACK_STREAM_SWITCH = 0x00000001
        }

        [Flags]
        enum CopyFileFlags : uint
        {
            COPY_FILE_FAIL_IF_EXISTS = 0x00000001,
            COPY_FILE_RESTARTABLE = 0x00000002,
            COPY_FILE_OPEN_SOURCE_FOR_WRITE = 0x00000004,
            COPY_FILE_ALLOW_DECRYPTED_DESTINATION = 0x00000008
        }
        #endregion

        #region 归类循环复制文件
        /// <summary>
        /// 复制失败文件
        /// </summary>
        public static List<string> noExistsList = new List<string>();
        public static List<string> sizeExistsList = new List<string>();

        /// <summary>
        /// 归类循环检查文件
        /// </summary>
        /// <param name="dir"></param>
        public static void ExistsFile(string dir)
        {
            if (string.IsNullOrWhiteSpace(dir)) return;
            if (!Directory.Exists(dir)) return;

            foreach (var file in Directory.GetFiles(dir))
            {
                StringBuilder sb = new StringBuilder();
                sb.Append(file);
                string newfile = file.Replace(oldPath, newPath);//文件新地址
                string newdir = Path.GetDirectoryName(newfile);
                if (!Directory.Exists(newdir)) Directory.CreateDirectory(newdir);

                FileInfo oldInfo = new FileInfo(file);//旧文件信息
                FileInfo newInfo = new FileInfo(newfile);//新文件信息

                if (!newInfo.Exists)//新文件不存在
                {
                    sb.Append(" 不存在 ");
                    if (!noExistsList.Contains(file))
                    {
                        noExistsList.Add(file);
                    }
                }
                else//新目录存在文件则比对大小
                {
                    sb.Append(" 存在,比大小 ");
                    if (oldInfo.Length != newInfo.Length)//旧目录大小和新目录大小不一样
                    {
                        if (!sizeExistsList.Contains(file))
                        {
                            sizeExistsList.Add(file);
                        }
                        sb.Append(" " + oldInfo.Length + "-->" + newInfo.Length + " 大小不一 ");
                    }
                    else//大小一致则调过
                    {
                        sb.Append(" 一致 ");
                    }
                }
                Console.WriteLine(sb.ToString());
            }

            foreach (var mydir in Directory.GetDirectories(dir))
            {
                ExistsFile(mydir);
            }
        }
        #endregion

        /// <summary>
        /// 输出日志并保存文件
        /// </summary>
        /// <param name="value"></param>
        public static void WriteLog(string value, ConsoleColor color = ConsoleColor.Gray)
        {
            try
            {

                if (string.IsNullOrWhiteSpace(value)) return;
                Console.ForegroundColor = color;
                Console.WriteLine(value);

                string path = DateTime.Now.ToString("yyyy-MM-dd-HH") + ".config";
                StreamWriter streamWriter = new StreamWriter(path, true);
                streamWriter.WriteLine(value);
                streamWriter.Close();
            }
            catch
            {
            }
        }

    }
}

 

标签:文件,file,Console,string,C#,Write,复制,进度,WriteLine
From: https://www.cnblogs.com/wxbug/p/16884917.html

相关文章

  • Asp.Net Core中使用日志组件log4net
    我们在开发任何项目过程中,记录各种日志是太正常不过的事情。没有日志记录的项目,也不可能放心进入生产环境运行。因此日志的记录,是必须要做的。在.NET开发中,log4net是个常......
  • C温故补缺(十):输入输出
    输入输出printf()和scanf()用来格式化输入输出,它们都是有返回值的intprintf()返回输出的内容的长度#include<stdio.h>intmain(){intc=printf("abcdefg\n");......
  • Oracle 19C学习 - 22. WITH AS 语句
    什么是WITHAS语句WITHAS相当于虚拟视图。WITHAS也叫做分解子查询或者片段子查询。定义一个SQL片段,该片段会被后面的SQL语句用到,可以近似看作一个可用的临时视图。......
  • (作者推荐)【RocketMQ入门到精通】— RocketMQ中级特性能力 | ​长轮询Pull和Push模式
    名言警句任何先进的技术均与魔法无异追本溯源【​​经历了6个月的失踪,我将带着干货终究归来!【RocketMQ入门到精通】​​】RocketMQ消费机制回顾   在众多MQ的体系中,一......
  • 第五章 RBAC访问控制
    Role-BasedAccessControl,基于角色的访问控制,apiserver启动参数添加--authorization-mode=RBAC来启用RBAC认证模式,kubeadm安装的集群默认已开启。​​官方介绍​​查看开......
  • 补档--【THM】Content Discovery(网站内容发现)-学习
    本文相关的TryHackMe实验房间链接:https://tryhackme.com/room/contentdiscovery通过学习相关知识点:了解在网络服务器上发现可能导致漏洞的隐藏或私人内容的各种方法(网站内......
  • Docker的介绍与安装
    Docker是什么Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的Linux或Windows操作系统的机器上,也可以实......
  • EXC_RETURN
    当任务启动或切换的SVC中断结束时,返回一个在r14的特殊值---EXC_RETURN,其决定返回后系统进入什么模式:1.线程模式orHandler模式;2.出栈操作的SP指向哪个栈:PSPorMSP。......
  • C++ 面经:项目常见问题 ----- nagle算法,keepalive,Linger 选项
    nagle算法应用场景:1.对于实时性要求很高的交互上,我们不能使用nagle算法,比如FPS射击类PVP对抗类游戏,或者MMO类的对实时要求很高的游戏开发来说是显而易见需要禁掉的,因为假......
  • Acwing第 77 场周赛
    (简单)4716.进球-AcWing题库#include<iostream>#include<map>usingnamespacestd;map<string,int>mp;intmain(){intn;cin>>n;s......