背景
电脑存了很多手机备份的照片,备份一次就是一个文件夹,比较分散,名字不方便查找,想统一放到一个文件夹内,按照年月分组,每一年每个月的照片放到一起。
所以用大半天时间用winform简单做了一个批处理工具。(winform不熟悉一直百度)
主要功能
主要功能:
- 文件按照年份和月份二级文件夹目录分组
- 可选按文件创建最早时间进行重命名
- 实时显示处理进度
- 默认复制文件,可选移动文件
- 简单去重(时间相等文件判断md5值)
- 支持取消
源文件:
新文件:
电梯直达
代码
using System;
using System.ComponentModel;
using System.Data;
using System.IO;
using System.Linq;
using System.Windows.Forms;
namespace HnoyiTools
{
public partial class HnoyiTools : Form
{
public HnoyiTools()
{
InitializeComponent();
}
//记录文件总数,显示进度
static long FileNum = 0;
static bool MoveEnable = false;
//随机数
private static Random random = new Random();
/// <summary>
/// 随机字符串
/// </summary>
/// <param name="chars"></param>
/// <param name="length"></param>
/// <returns></returns>
public string GetRandomStr(string chars, int length)
{
if (string.IsNullOrEmpty(chars))
{
chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghizklmnopqrstuvwxyz0123456789";
}
//const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
return new string(Enumerable.Repeat(chars, length)
.Select(s => s[random.Next(s.Length)]).ToArray());
}
private void SrcPathbutton_Click(object sender, EventArgs e)
{
FolderBrowserDialog folder = new FolderBrowserDialog();
folder.Description = "选择文件所在文件夹目录"; //提示的文字
if (folder.ShowDialog() == DialogResult.OK)
{
SrcPathBox.Text = folder.SelectedPath;
}
}
private void DestPathbutton_Click(object sender, EventArgs e)
{
FolderBrowserDialog folder = new FolderBrowserDialog();
folder.Description = "选择文件所在文件夹目录"; //提示的文字
if (folder.ShowDialog() == DialogResult.OK)
{
DestPathBox.Text = folder.SelectedPath;
}
}
private void BackWorker_DoWork(object sender, DoWorkEventArgs e)
{
// 遍历所有文件
var files = Directory.GetFiles(SrcPathBox.Text, "*.*", SearchOption.AllDirectories);
int i = 0;
foreach (var file in files)
{
//判断退出
if (BackWorker.CancellationPending == true)
{
e.Cancel = true;
break;
}
//获取文件创建时间等信息
FileInfo fi = new FileInfo(file);
/*
Console.WriteLine("创建时间:" + fi.CreationTime);
Console.WriteLine("修改时间:" + fi.LastWriteTime);
Console.WriteLine("访问时间:" + fi.LastAccessTime);
*/
//取最早时间,copy的文件创建时间会很新
DateTime Time = fi.CreationTime;
if (DateTime.Compare(fi.CreationTime, fi.LastWriteTime) > 0)
{
Time = fi.LastWriteTime;
}
//按年月方式创建目录
string DestPath = DestPathBox.Text + @"\" + Time.Year + @"\" + Time.Month + @"\";
if (!Directory.Exists(DestPath))
{
Directory.CreateDirectory(DestPath);
}
//重命名文件
string SourceFile = file;
string DestFile = DestPath + Time.ToString("yyyy-MM-dd__HH_mm_ss") + fi.Extension;
//防止重名
if (File.Exists(DestFile))
{
DestFile = DestPath + Time.ToString("yyyy-MM-dd__HH_mm_ss") + "_" + GetRandomStr(null, 4) + fi.Extension;
}
//移动文件
if (MoveEnable)
{
File.Move(SourceFile, DestFile);
}
else
{
//默认复制文件
File.Copy(SourceFile, DestFile);
}
//通知进度
string ProcessMsg = "原文件:" + SourceFile + "\r\n" + "新文件" + DestFile + "\r\n";
//Console.WriteLine(ProcessMsg);
i++;
BackWorker.ReportProgress(i, ProcessMsg);
}
}
private void BackWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
//BackWorker.ReportProgress方法传递过来的参数userState
string state = (string)e.UserState;
progressBar.Value = e.ProgressPercentage;
ProgresLabel.Text = "处理进度:" + Convert.ToString(e.ProgressPercentage) + "/" + FileNum;
MsgBox.Text += e.UserState.ToString();
}
private void BackWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//计算过程中的异常会被抓住,在这里可以进行处理。
//这里没做异常处理
if (e.Error != null)
{
Type errorType = e.Error.GetType();
switch (errorType.Name)
{
case "ArgumentNullException":
case "MyException":
//do something.
break;
default:
//do something.
break;
}
}
}
private void StartWorkButton_Click(object sender, EventArgs e)
{
//判断是否正在运行异步操作
if (BackWorker.IsBusy)
return;
if (SrcPathBox.Text.Length < 1 || DestPathBox.Text.Length < 1)
{
MessageBox.Show("请选择源文件目录和目标文件夹目录!");
return;
}
//
//判断文件操作模式
if (MoveCheckBox.Checked)
{
MoveEnable = true;
}
//清空显示
ProgresLabel.Text = "处理进度:";
MsgBox.Text = "";
//填充总文件数表示进度
FileNum = progressBar.Maximum = Directory.GetFiles(SrcPathBox.Text, "*.*", SearchOption.AllDirectories).Length;
//给业务传递参数,就是把前台的要处理的参数传递进去
BackWorker.RunWorkerAsync();
StopWorkButton.Enabled = true;
}
private void StopWorkButton_Click(object sender, EventArgs e)
{
//取消后台进程
BackWorker.CancelAsync();
}
}
}