3x5w4rup

Duplicate File Finder

Jul 7th, 2014
380
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 19.33 KB | None | 0 0
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.IO;
  5. using System.Security.Cryptography;
  6. using System.Text;
  7. using System.Threading;
  8. using System.Windows.Forms;
  9.  
  10. namespace Duplicate_File_Finder
  11. {
  12.     public partial class Form1 : Form
  13.     {
  14.         public Form1()
  15.         {
  16.             InitializeComponent();
  17.         }
  18.  
  19.         private void Form1_Load(object sender, EventArgs e)
  20.         {
  21.             // At the Form1_Load I made sure that the groupbox was not enabled until the checkbox "cbxSearchByFileType" was checked.
  22.             // I also made sure the Treeview would have checkboxes (to enable easy deletion of the files)
  23.             gbxSearchByFiletype.Enabled = false;
  24.             txtSearchLocation.Enabled = false;
  25.             Duplicates.CheckBoxes = true;
  26.  
  27.             pgbProgress.Minimum = 0;
  28.             pgbProgress.Maximum = 100;
  29.         }
  30.  
  31.         Hashtable fileHashes;           //A hashtable to hold the hashes of every file.
  32.         List<string> fileEntries;       //A List to hold the path of every file
  33.         double bytesWasted;             //A double to count the bytes that are wasted because of duplicates.
  34.  
  35.         #region Controls
  36.  
  37.         private void cbxSearchByFileType_CheckedChanged(object sender, EventArgs e)
  38.         {
  39.             //This if/else statement checks if the Checkbox is checked, if it is, the groupbox should enable, if not, the groupbox should disable.
  40.             if (cbxSearchByFileType.Checked == true)
  41.             {
  42.                 gbxSearchByFiletype.Enabled = true;
  43.             }
  44.             else
  45.             {
  46.                 gbxSearchByFiletype.Enabled = false;
  47.             }
  48.         }
  49.  
  50.         private void btnSearchLocation_Click(object sender, EventArgs e)
  51.         {
  52.             //Opens a folderdialog to specify the path to search for duplicates.
  53.             FolderBrowserDialog dialog = new FolderBrowserDialog();
  54.             DialogResult result = dialog.ShowDialog();
  55.             if (result == DialogResult.OK)
  56.             {
  57.                 txtSearchLocation.Text = dialog.SelectedPath.ToString();
  58.             }
  59.         }
  60.  
  61.         private void DeleteFiles_Click(object sender, EventArgs e)
  62.         {
  63.             //This loops through all nodes in the Treeview Duplicates to check if the checkbox is checked, if it is, it deletes the file.
  64.             foreach (TreeNode node in Duplicates.Nodes)
  65.             {
  66.                 for (int i = 0; i < node.GetNodeCount(false); i++)
  67.                 {
  68.                     if (node.Nodes[i].Checked == true)
  69.                     {
  70.                         File.Delete(node.Nodes[i].Text);
  71.                         node.Nodes[i].Remove();
  72.                     }
  73.                 }
  74.             }
  75.         }
  76.  
  77.         private void searchDups_Click(object sender, EventArgs e)
  78.         {
  79.             //Whenever the button "Find Duplicates" is pressed, we make sure that all variables is clean
  80.             //Then we start a thread to do the work.
  81.             ClearVariables();
  82.             Thread t = new Thread(new ThreadStart(DoWork));
  83.             t.IsBackground = true;
  84.             t.Start();
  85.         }
  86.         #endregion
  87.  
  88.         #region DoWork Function
  89.         private void DoWork()
  90.         {
  91.             //Check if any path is specified
  92.             if (txtSearchLocation.Text.Length == 0)
  93.             {
  94.                 MessageBox.Show("You have to specify a directory to scan", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
  95.             }
  96.             else
  97.             {
  98.                 //Check if the "Search By filetype" is checked, and which filetypes they want to search for
  99.                 if (cbxSearchByFileType.Checked == true)
  100.                 {
  101.                     //A LOT of If statements to check which checkboxes are checked.
  102.                     if (cbxAudioSearch.Checked == true)
  103.                     {
  104.                         //This pattern repeats throughout all the if-statements
  105.                         //Create a try-catch to catch the error if we don't have access to the specified path
  106.                         try
  107.                         {
  108.                             //Create some arrays to hold all the files + path to the file
  109.                             string[] audioFiles = Directory.GetFileSystemEntries(txtSearchLocation.Text, "*.wav", SearchOption.AllDirectories);
  110.                             string[] audioFiles2 = Directory.GetFileSystemEntries(txtSearchLocation.Text, "*.mp3", SearchOption.AllDirectories);
  111.  
  112.                             //Loop through the arrays and add the strings to the list "FileEntries"
  113.                             foreach (string audio in audioFiles)
  114.                             {
  115.                                 fileEntries.Add(audio);
  116.                             }
  117.                             foreach (string audio in audioFiles2)
  118.                             {
  119.                                 fileEntries.Add(audio);
  120.                             }
  121.                         }
  122.                         catch (UnauthorizedAccessException UAX)
  123.                         {
  124.                             MessageBox.Show(UAX.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
  125.                         }
  126.                     }
  127.                     if (cbxDocumentSearch.Checked == true)
  128.                     {
  129.                         try
  130.                         {
  131.                             string[] documentFiles = Directory.GetFileSystemEntries(txtSearchLocation.Text, "*.txt", SearchOption.AllDirectories);
  132.                             string[] documentFiles2 = Directory.GetFileSystemEntries(txtSearchLocation.Text, "*.doc", SearchOption.AllDirectories);
  133.                             string[] documentFiles3 = Directory.GetFileSystemEntries(txtSearchLocation.Text, "*.rtf", SearchOption.AllDirectories);
  134.  
  135.                             foreach (string document in documentFiles)
  136.                             {
  137.                                 fileEntries.Add(document);
  138.                             }
  139.                             foreach (string document in documentFiles2)
  140.                             {
  141.                                 fileEntries.Add(document);
  142.                             }
  143.                             foreach (string document in documentFiles3)
  144.                             {
  145.                                 fileEntries.Add(document);
  146.                             }
  147.                         }
  148.                         catch (UnauthorizedAccessException UAX)
  149.                         {
  150.                             MessageBox.Show(UAX.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
  151.                         }
  152.                     }
  153.                     if (cbxPictureSearch.Checked == true)
  154.                     {
  155.                         try
  156.                         {
  157.                             string[] pictureFiles = Directory.GetFileSystemEntries(txtSearchLocation.Text, "*.jpg", SearchOption.AllDirectories);
  158.                             string[] pictureFiles2 = Directory.GetFileSystemEntries(txtSearchLocation.Text, "*.jpeg", SearchOption.AllDirectories);
  159.                             string[] pictureFiles3 = Directory.GetFileSystemEntries(txtSearchLocation.Text, "*.bmp", SearchOption.AllDirectories);
  160.                             string[] pictureFiles4 = Directory.GetFileSystemEntries(txtSearchLocation.Text, "*.png", SearchOption.AllDirectories);
  161.                             string[] pictureFiles5 = Directory.GetFileSystemEntries(txtSearchLocation.Text, "*.gif", SearchOption.AllDirectories);
  162.  
  163.                             foreach (string picture in pictureFiles)
  164.                             {
  165.                                 fileEntries.Add(picture);
  166.                             }
  167.                             foreach (string picture in pictureFiles2)
  168.                             {
  169.                                 fileEntries.Add(picture);
  170.                             }
  171.                             foreach (string picture in pictureFiles3)
  172.                             {
  173.                                 fileEntries.Add(picture);
  174.                             }
  175.                             foreach (string picture in pictureFiles4)
  176.                             {
  177.                                 fileEntries.Add(picture);
  178.                             }
  179.                             foreach (string picture in pictureFiles5)
  180.                             {
  181.                                 fileEntries.Add(picture);
  182.                             }
  183.                         }
  184.                         catch (UnauthorizedAccessException UAX)
  185.                         {
  186.                             MessageBox.Show(UAX.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
  187.                         }
  188.                     }
  189.                     if (cbxVideoSearch.Checked == true)
  190.                     {
  191.                         try
  192.                         {
  193.                             string[] videoFiles = Directory.GetFileSystemEntries(txtSearchLocation.Text, "*.mp4", SearchOption.AllDirectories);
  194.                             string[] videoFiles2 = Directory.GetFileSystemEntries(txtSearchLocation.Text, "*.mkv", SearchOption.AllDirectories);
  195.                             string[] videoFiles3 = Directory.GetFileSystemEntries(txtSearchLocation.Text, "*.avi", SearchOption.AllDirectories);
  196.  
  197.                             foreach (string video in videoFiles)
  198.                             {
  199.                                 fileEntries.Add(video);
  200.                             }
  201.                             foreach (string video in videoFiles2)
  202.                             {
  203.                                 fileEntries.Add(video);
  204.                             }
  205.                             foreach (string video in videoFiles3)
  206.                             {
  207.                                 fileEntries.Add(video);
  208.                             }
  209.                         }
  210.                         catch (UnauthorizedAccessException UAX)
  211.                         {
  212.                             MessageBox.Show(UAX.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
  213.                         }
  214.                     }
  215.                     if (txtCustomFileType.Text.Length != 0)
  216.                     {
  217.                         try
  218.                         {
  219.                             string[] customFiles = Directory.GetFileSystemEntries(txtSearchLocation.Text, "*." + txtCustomFileType.Text, SearchOption.AllDirectories);
  220.  
  221.                             foreach (string customFile in customFiles)
  222.                             {
  223.                                 fileEntries.Add(customFile);
  224.                             }
  225.                         }
  226.                         catch (UnauthorizedAccessException UAX)
  227.                         {
  228.                             MessageBox.Show(UAX.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
  229.                         }
  230.                     }
  231.                 }
  232.                     //If they didn't want to search by filetype
  233.                 else
  234.                 {
  235.                     //Same pattern as before with the try-catch
  236.                     try
  237.                     {
  238.                         //and the arrays.                           But here there is an option to search all files by just entering "*"
  239.                         string[] files = Directory.GetFileSystemEntries(txtSearchLocation.Text, "*", SearchOption.AllDirectories);
  240.                         foreach (string file in files)
  241.                         {
  242.                             fileEntries.Add(file);
  243.                         }
  244.                     }
  245.                     catch (UnauthorizedAccessException UAX)
  246.                     {
  247.                         MessageBox.Show(UAX.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
  248.                     }
  249.                 }
  250.  
  251.                 //Then we loop through each file in "FileEntries"
  252.                 for (int i = 0; i < fileEntries.Count; i++)
  253.                 {
  254.                     //Calls "CreateHash" to get our hash
  255.                     string hash = CreateHash(fileEntries[i]);
  256.                     //Check if we actually got a hash
  257.                     if (hash != "")
  258.                     {
  259.                         //Call "SearchDups" to check for duplicates
  260.                         string duplicateFile = SearchDups(hash);
  261.                         if (duplicateFile != "")
  262.                         {
  263.                             //If there was a duplicate, calculate the percentage of completion and call "AddNodes"
  264.                             int percentage = Convert.ToInt32(i * 100 / fileEntries.Count);
  265.                             AddNodes("FILL", fileEntries[i], duplicateFile, hash, percentage);
  266.                         }
  267.                         //At last, we add the new hash to our hashtable
  268.                         fileHashes.Add(fileEntries[i], hash);
  269.                     }
  270.                 }
  271.                 //When the loop is completed we once again call "AddNodes" with the argument "PROGRESSCOMPLETED" to indicate that we're done.
  272.                 AddNodes("PROGRESSCOMPLETED", string.Empty, string.Empty, string.Empty, 0);
  273.             }            
  274.         }
  275.         #endregion
  276.  
  277.         #region CrossThread Stuff
  278.  
  279.         //This is the cross-threading part, I've actually never really tried this before, so this was a new concept for me in this competition.
  280.         //We create a delegate to invoke our calls to the controls in the main-thread
  281.         private delegate void AddNodesDel(string arg, string newFile, string oldFile, string hash, int percentage);
  282.         //And the function "AddNodes"
  283.         public void AddNodes(string arg, string newFile, string oldFile, string hash, int percentage)
  284.         {
  285.             //This is self-explanatory, if there's required an invoke, we create a new AddNodesDel delegate to invoke our calls
  286.             if (InvokeRequired)
  287.             {
  288.                 Invoke(new AddNodesDel(AddNodes), new object[] { arg, newFile, oldFile, hash, percentage });
  289.             }
  290.             else
  291.             {
  292.                 //Switch the string "arg" to check what to do
  293.                 switch (arg)
  294.                 {
  295.                         //If the progress is completed, indicate it by completely filling the ProgressBar
  296.                     case "PROGRESSCOMPLETED":
  297.                         pgbProgress.Value = 100;
  298.                         break;
  299.  
  300.                         //If we want to "fill" our treeview
  301.                     case "FILL":
  302.                         //Create a new array of treenodes to check if we can find a matching hash somewhere
  303.                         TreeNode[] nodes = Duplicates.Nodes.Find(hash, true);
  304.                         if (nodes.Length != 0)
  305.                         {
  306.                             //If we could we loop through the nodes with the same hash (even though there should only be one) add the new file to the treeview and update the Byteswasted label
  307.                             for (int p = 0; p < nodes.Length; p++)
  308.                             {
  309.                                 nodes[p].Nodes.Add(newFile);                                
  310.                                 lblWastingBytes.Text = String.Format("{0:0.00}", ((bytesWasted / 1024.0) / 1024.0)) + " MB";
  311.                             }
  312.                         }
  313.                         else
  314.                         {
  315.                             //If we couldn't find the hash in the treeview, we create a new node with the two duplicates as children and update the Bytewasted label
  316.                             TreeNode newNote = new TreeNode();
  317.                             newNote.Text = hash.ToUpper();
  318.                             newNote.Name = hash;
  319.                             newNote.ForeColor = System.Drawing.Color.DarkRed;
  320.                             newNote.Nodes.Add(newFile);
  321.                             newNote.Nodes.Add(oldFile);
  322.                             Duplicates.Nodes.Add(newNote);
  323.                            
  324.                             lblWastingBytes.Text = String.Format("{0:0.00}", ((bytesWasted / 1024.0) / 1024.0)) + " MB";
  325.                         }
  326.                         //At last we update the Progressbar
  327.                         pgbProgress.Value = percentage;
  328.                         break;
  329.                 }
  330.             }
  331.         }
  332.         #endregion
  333.  
  334.         #region User defined functions
  335.  
  336.         //This function clears all controls and variavbles that needs clearing.
  337.         private void ClearVariables()
  338.         {
  339.             fileHashes = new Hashtable();
  340.             fileEntries = new List<string>();
  341.             bytesWasted = 0.0;
  342.  
  343.             lblWastingBytes.Text = String.Empty;
  344.             Duplicates.Nodes.Clear();
  345.             pgbProgress.Value = 0;
  346.         }
  347.  
  348.         //This function loops through the hashtable to see if there is any duplicates of the hash in there, if there is it returns the filename of the duplicate of the hash.
  349.         public string SearchDups(string hash)
  350.         {
  351.             IDictionaryEnumerator en = fileHashes.GetEnumerator();
  352.             while (en.MoveNext())
  353.             {
  354.                 if (hash == en.Value.ToString())
  355.                 {
  356.                     return en.Key.ToString();
  357.                 }
  358.             }
  359.             return "";
  360.         }
  361.  
  362.         //This function gets a filepath as argument
  363.         public string CreateHash(string filePath)
  364.         {
  365.             //Create a new SHA256 hash creator (Sorry, I don't know what to call it?)
  366.             SHA256 shaM = new SHA256Managed();
  367.             try
  368.             {
  369.                 //Filestream opens the filepath
  370.                 FileStream file = new FileStream(filePath, FileMode.Open, FileAccess.Read);
  371.  
  372.                 //Compute a hash of the bytes in the file
  373.                 byte[] result = shaM.ComputeHash(file);
  374.  
  375.                
  376.                 StringBuilder builder = new StringBuilder();
  377.                 foreach (byte b in result)
  378.                 {
  379.                     //Loop through each byte in the result and append it to the string, and a trick HSP teached me to add the "x2" to make it HEX values.
  380.                     builder.Append(b.ToString("x2"));
  381.                 }
  382.                 //store the hash
  383.                 string hash = builder.ToString();
  384.  
  385.                 //And if the hashtable contains the hash, we might as well add the bytes to byteswasted while the file is open allready.
  386.                 if (fileHashes.ContainsValue(hash)) { bytesWasted += file.Length; }
  387.  
  388.                 //Close off and return the hash.
  389.                 builder.Clear();
  390.                 file.Close();
  391.  
  392.                 return hash;
  393.             }
  394.                 //Catch to control if there is any file (There should be, but just in case)
  395.             catch (FileNotFoundException ex)
  396.             {
  397.                 MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
  398.                 return "";
  399.             }
  400.                 //Catch to see if we don't have authorization to access the file
  401.             catch (UnauthorizedAccessException)
  402.             {
  403.                 return "";
  404.             }
  405.         }
  406.         #endregion
  407.     }
  408. }
Add Comment
Please, Sign In to add comment