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
{
}
}
}
}