- [SQLSERVER] Loại bỏ Restricted User trên database MSSQL
- [C#] Hướng dẫn tạo mã QRcode Style trên winform
- [C#] Hướng dẫn sử dụng temp mail service api trên winform
- [C#] Hướng dẫn tạo mã thanh toán VietQR Pay không sử dụng API trên winform
- [C#] Hướng Dẫn Tạo Windows Service Đơn Giản Bằng Topshelf
- [C#] Chia sẻ source code đọc dữ liệu từ Google Sheet trên winform
- [C#] Chia sẻ source code tạo mã QR MOMO đa năng Winform
- [C#] Chia sẻ source code phần mềm lên lịch tự động chạy ứng dụng Scheduler Task Winform
- [Phần mềm] Tải và cài đặt phần mềm Sublime Text 4180 full version
- [C#] Hướng dẫn download file từ Minio Server Winform
- [C#] Hướng dẫn đăng nhập zalo login sử dụng API v4 trên winform
- [SOFTWARE] Phần mềm gởi tin nhắn Zalo Marketing Pro giá rẻ mềm nhất thị trường
- [C#] Việt hóa Text Button trên MessageBox Dialog Winform
- [DEVEXPRESS] Chia sẻ code các tạo report in nhiều hóa đơn trên XtraReport C#
- [POWER AUTOMATE] Hướng dẫn gởi tin nhắn zalo từ file Excel - No code
- [C#] Chia sẻ code lock và unlock user trong domain Window
- [DEVEXPRESS] Vẽ Biểu Đồ Stock Chứng Khoán - Công Cụ Thiết Yếu Cho Nhà Đầu Tư trên Winform
- [C#] Hướng dẫn bảo mật ứng dụng 2FA (Multi-factor Authentication) trên Winform
- [C#] Hướng dẫn convert HTML code sang PDF File trên NetCore 7 Winform
- [C#] Hướng dẫn viết ứng dụng chat với Gemini AI Google Winform
[C#] Tìm kiếm file trùng nhau trong cùng thư mục lập trình Winform
Xin chào các bạn, bài viết hôm nay mình sẽ hướng dẫn các bạn cách tìm kiếm file trùng nhau trên cùng một thư mục Windows bằng ngôn ngữ lập trình C#.
[C#] Find Duplicate File in Directory Winform
Trong mỗi người chúng ta, thường hay sử dụng chép nhạc hay file ảnh hoặc một tập tin gì đó qua lại giữa các folder hoặc chung một folder.
Thường các bạn sẽ dễ tìm thấy, sau thời gian chúng ta sử dụng sẽ phát sinh nhiều file trùng giống nhau, nguyên nhân chính là do Copy
.
Thay vì chúng ta tìm kiếm thủ công nó để xóa, thì chúng ta có thể viết một ứng dụng nhỏ để tìm file nào giống nhau, và liệt kê ra danh sách cho chúng ta xóa một cách dễ dàng.
Vậy làm thế nào để biết được file có trùng hay không?
Trong bài viết này, mình sẽ kiểm tra checksum file hash của từng file, nếu file nào có trùng mã hash, thì file đó là file trùng và mình liệt kê vào một group.
Các bạn có thể tìm hiểu checksum file ở bài viết trước qua link ở đây: Checksum file in C#
Dưới đây là giao diện demo ứng dụng tìm kiếm file trùng nhau C#:
Source code C# Check file trùng trên Winform:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.VisualBasic.FileIO;
using System.IO;
using System.Security.Cryptography;
using System.Runtime.InteropServices;
using System.Diagnostics;
namespace howto_find_duplicate_files
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
txtDirectory.Text = Properties.Settings.Default.Directory;
splitContainer1.Panel2.BackColor = Color.White;
picImage.SizeMode = PictureBoxSizeMode.Zoom;
picImage.Dock = DockStyle.Fill;
picImage.Visible = false;
rchText.Dock = DockStyle.Fill;
rchText.Visible = false;
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
Properties.Settings.Default.Directory = txtDirectory.Text;
Properties.Settings.Default.Save();
}
private void btnBrowse_Click(object sender, EventArgs e)
{
fbdDirectory.SelectedPath = txtDirectory.Text;
if (fbdDirectory.ShowDialog() == DialogResult.OK)
txtDirectory.Text = fbdDirectory.SelectedPath;
}
private void btnSearch_Click(object sender, EventArgs e)
{
Stopwatch watch = new Stopwatch();
watch.Start();
Cursor = Cursors.WaitCursor;
trvFiles.Visible = false;
trvFiles.Nodes.Clear();
lblNumDuplicates.Text = "";
Refresh();
try
{
var get_info =
from string filename in Directory.GetFiles(txtDirectory.Text)
select new
{
Name = filename,
Hash = BytesToString(GetHash(filename))
};
var group_infos =
from info in get_info
group info by info.Hash into g
where g.Count() > 1
//orderby g.Key
select g;
int num_groups = 0;
int num_files = 0;
foreach (var g in group_infos)
{
num_groups++;
TreeNode hash_node = trvFiles.Nodes.Add(g.Key.ToString());
foreach (var info in g)
{
num_files++;
TreeNode file_node = new TreeNode(info.Name);
file_node.Tag = new FileInfo(info.Name);
hash_node.Nodes.Add(file_node);
}
}
lblNumDuplicates.Text =
(num_files - num_groups).ToString() +
" files trùng.";
trvFiles.ExpandAll();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
if (trvFiles.Nodes.Count > 0)
trvFiles.Nodes[0].EnsureVisible();
trvFiles.Visible = true;
Cursor = Cursors.Default;
}
watch.Stop();
Console.WriteLine(watch.Elapsed.TotalSeconds.ToString("0.00") + " seconds");
}
private void trvFiles_AfterSelect(object sender, TreeViewEventArgs e)
{
if (Deleting) return;
rchText.Visible = false;
picImage.Visible = false;
Refresh();
if (e.Node.Level == 0) return;
FileInfo file_info = e.Node.Tag as FileInfo;
switch (file_info.Extension.ToLower())
{
case ".txt":
case ".html":
case ".cs":
case ".csproj":
case ".resx":
case ".xml":
case ".xaml":
case ".config":
rchText.Text = File.ReadAllText(file_info.FullName);
rchText.Visible = true;
break;
case ".rtf":
rchText.LoadFile(file_info.FullName);
rchText.Visible = true;
break;
case ".jpg":
case ".jpeg":
case ".gif":
case ".png":
case ".tiff":
case ".bmp":
picImage.Image = LoadBitmapUnlocked(file_info.FullName);
picImage.Visible = true;
break;
default:
rchText.Text = "Unknown file extension " + file_info.Extension;
rchText.Visible = true;
break;
}
}
private void btnSelectDuplicates_Click(object sender, EventArgs e)
{
foreach (TreeNode hash_node in trvFiles.Nodes)
{
hash_node.Checked = false;
hash_node.Nodes[0].Checked = false;
for (int i = 1; i < hash_node.Nodes.Count; i++)
hash_node.Nodes[i].Checked = true;
}
}
private bool Deleting = false;
private void btnDeleteSelected_Click(object sender, EventArgs e)
{
Deleting = true;
trvFiles.Visible = false;
lblNumDuplicates.Text = "";
picImage.Visible = false;
picImage.Image = null;
rchText.Visible = false;
Cursor = Cursors.WaitCursor;
Refresh();
try
{
List<TreeNode> nodes_to_delete = new List<TreeNode>();
foreach (TreeNode hash_node in trvFiles.Nodes)
{
foreach (TreeNode file_node in hash_node.Nodes)
{
if (file_node.Checked) nodes_to_delete.Add(file_node);
}
}
foreach (TreeNode file_node in nodes_to_delete)
{
FileInfo file_info = file_node.Tag as FileInfo;
DeleteFile(file_info.FullName);
file_node.Remove();
}
nodes_to_delete = new List<TreeNode>();
foreach (TreeNode hash_node in trvFiles.Nodes)
{
if (hash_node.Nodes.Count == 0) nodes_to_delete.Add(hash_node);
}
foreach (TreeNode hash_node in nodes_to_delete)
{
hash_node.Remove();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
if (trvFiles.Nodes.Count > 0)
trvFiles.Nodes[0].EnsureVisible();
trvFiles.Visible = true;
Deleting = false;
Cursor = Cursors.Default;
}
}
public static void DeleteFile(string filename)
{
DeleteFile(filename, false, false);
}
public static void DeleteFile(string filename, bool confirm)
{
DeleteFile(filename, confirm, false);
}
public static void DeleteFile(string filename, bool confirm, bool delete_permanently)
{
UIOption ui_option = UIOption.OnlyErrorDialogs;
if (confirm) ui_option = UIOption.AllDialogs;
RecycleOption recycle_option =
recycle_option = RecycleOption.SendToRecycleBin;
if (delete_permanently)
recycle_option = RecycleOption.DeletePermanently;
try
{
FileSystem.DeleteFile(filename, ui_option, recycle_option);
}
catch (Exception ex)
{
MessageBox.Show("Error deleting file.\n" + ex.Message,
"Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void trvFiles_AfterCheck(object sender, TreeViewEventArgs e)
{
if (e.Node.Level == 0)
{
foreach (TreeNode file_node in e.Node.Nodes)
{
file_node.Checked = e.Node.Checked;
}
}
}
private MD5 Md5 = MD5.Create();
private byte[] GetHash(string filename)
{
using (FileStream stream = File.OpenRead(filename))
{
return Md5.ComputeHash(stream);
}
}
private string BytesToString(byte[] bytes)
{
string result = "";
foreach (byte b in bytes) result += b.ToString("x2");
return result;
}
private Bitmap LoadBitmapUnlocked(string file_name)
{
using (Bitmap bm = new Bitmap(file_name))
{
return new Bitmap(bm);
}
}
}
}
Thanks for watching!