12 #region Private Attributes
14 private const string DUPLICATED_FILES_JSON =
"C:\\Users\\Alexa\\repos\\duplicate-file-locator\\duplicated-images.json";
15 private const string DEFAULT_TXT_OUTPUT_PATH =
"C:\\Users\\Alexa\\repos\\duplicate-file-locator\\duplicated-images.txt";
18 private string _duplicatedFilesJson;
20 private List<IDuplicatedFile> _duplicatedFiles;
31 _duplicatedFiles =
new List<IDuplicatedFile>();
38 _duplicatedFilesJson = jsonPath;
40 _duplicatedFiles =
new List<IDuplicatedFile>();
47 #region Public Methods
56 List<string> filePaths = GetAllFilesInDirectory(dir);
57 int totalFiles = filePaths.Count;
64 List<string> hashesFound =
new List<string>();
66 for (
int i = 0; i < filePaths.Count; i++)
69 int progress = (filesHashed * 100) / totalFiles;
70 ConsoleUtility.WriteProgressBar(progress,
true);
72 string hash = CreateHash(filePaths[i]);
75 if (CheckHash(hash, hashesFound))
77 AddDuplicateFile(hash, filePaths[i]);
79 filePaths.Remove(filePaths[i]);
85 hashesFound.Add(hash);
89 ConsoleUtility.WriteProgressBar(100,
true);
90 Console.WriteLine(
"\nTotal Images checked : {0}\nCollating Data now...\n", filesHashed);
97 FindOriginalPaths(filePaths, hashesFound);
103 Console.WriteLine(
"There are no files in this directory and it's subdirectories, please try again.\n");
109 Console.WriteLine(
"Path does not exist, please try again.\n");
116 Console.WriteLine(
"Verifying duplicate files found...\n");
119 List<string> notDuplicatePaths =
new List<string>();
121 for (
int i = 0; i < _duplicatedFiles.Count; i++)
123 string ogPath = _duplicatedFiles[i].OriginalPath;
124 Bitmap img1 =
new Bitmap(ogPath);
125 foreach (var duplicatedPath
in _duplicatedFiles[i].DuplicatePaths)
127 Bitmap img2 =
new Bitmap(duplicatedPath);
129 if (!AreImagesEqual(img1, img2))
132 notDuplicatePaths.Add(duplicatedPath);
138 if (notDuplicatePaths.Count > 1)
141 temp.OriginalPath = notDuplicatePaths[0];
142 notDuplicatePaths.RemoveAt(0);
143 foreach (var path
in notDuplicatePaths)
145 temp.AddDuplicatePath(path);
148 _duplicatedFiles.Add(temp);
152 notDuplicatePaths =
new List<string>();
159 Console.WriteLine(ToString());
164 if (_duplicatedFilesJson !=
null)
166 using (StreamWriter sw = File.CreateText(_duplicatedFilesJson))
173 using (StreamWriter sw = File.CreateText(DUPLICATED_FILES_JSON))
179 Console.WriteLine(
"Duplicate file cleared.\n");
184 using (StreamWriter sw = File.CreateText(DEFAULT_TXT_OUTPUT_PATH))
186 sw.WriteLine(ToString());
188 Console.WriteLine(
"Duplicate file exported.\n");
193 using (StreamWriter sw = File.CreateText(filePath))
195 sw.WriteLine(ToString());
197 Console.WriteLine(
"Duplicate file exported.\n");
202 if (Path.Exists(filePath))
204 string hash = CreateHash(filePath);
205 Console.WriteLine(
"Hash : {0}\n", hash);
209 Console.WriteLine(
"Path does not exist, please try again.\n");
215 #region Private Methods
226 private List<string> GetAllFilesInDirectory(
string dir)
228 List<string> files =
new List<string>();
229 if (Directory.Exists(dir))
231 List<string> subdirs = Directory.GetDirectories(dir).ToList<
string>();
232 foreach (
string subdir
in subdirs)
234 files.AddRange(GetAllFilesInDirectory(subdir));
238 files.AddRange(Directory.GetFiles(dir).ToList<
string>());
252 private string ByteArrayToString(
byte[] arrInput)
255 StringBuilder sOutput =
new StringBuilder(arrInput.Length);
256 for (i = 0; i < arrInput.Length; i++)
258 sOutput.Append(arrInput[i].ToString(
"X2"));
260 return sOutput.ToString();
272 private string CreateHash(
string filePath)
276 Bitmap img =
new Bitmap(filePath);
282 MemoryStream stream =
new MemoryStream();
283 img.Save(stream, System.Drawing.Imaging.ImageFormat.Bmp);
284 tmpSource = stream.ToArray();
287 tmpHash =
new MD5CryptoServiceProvider().ComputeHash(tmpSource);
289 return ByteArrayToString(tmpHash);
307 private void AddDuplicateFile(
string hash,
string filePath)
309 if (_duplicatedFiles.Any(file => file.Hash == hash))
312 IDuplicatedFile duplicateFile = _duplicatedFiles.FirstOrDefault(file => file.Hash == hash);
324 _duplicatedFiles.Add(
new DuplicatedFile(hash, filePath));
338 private void FindOriginalPaths(List<string> filePaths, List<string> hashesFound)
340 if (filePaths.Count == hashesFound.Count)
342 foreach (var file
in _duplicatedFiles)
345 if (file.OriginalPath ==
string.Empty)
347 int i = hashesFound.IndexOf(file.Hash);
352 string ogPath = filePaths[i];
353 file.OriginalPath = ogPath;
361 Console.WriteLine(
"Note: Can't find original files as filePaths and hashesFound are different in length.\n");
368 private void LoadData()
370 string json =
string.Empty;
371 if (_duplicatedFilesJson !=
null)
373 json = File.ReadAllText(_duplicatedFilesJson);
377 json = File.ReadAllText(DUPLICATED_FILES_JSON);
382 var deserialized = JsonConvert.DeserializeObject<List<DuplicatedFile>>(json);
383 _duplicatedFiles = deserialized.Cast<IDuplicatedFile>().ToList();
394 private void SaveData()
396 string json = JsonConvert.SerializeObject(_duplicatedFiles);
398 if (_duplicatedFilesJson !=
null)
400 File.WriteAllText(_duplicatedFilesJson, json);
404 File.WriteAllText(DUPLICATED_FILES_JSON, json);
412 private string ToString()
414 string output = String.Empty;
415 foreach (var file
in _duplicatedFiles)
417 output += file +
"\n";
420 if (output == String.Empty)
422 output =
"No duplicate files found.";
440 private bool AreImagesEqual(Bitmap bmp1, Bitmap bmp2)
442 if (bmp1.Width != bmp2.Width || bmp1.Height != bmp2.Height)
445 for (
int y = 0; y < bmp1.Height; y++)
447 for (
int x = 0; x < bmp1.Width; x++)
449 if (bmp1.GetPixel(x, y) != bmp2.GetPixel(x, y))
463 private bool CheckHash(
string hash, List<string> hashesFound)
465 if (hash ==
string.Empty)
470 return _duplicatedFiles.Any(file => file.Hash == hash) || hashesFound.Contains(hash);