using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Drawing;
using System.IO;
namespace Tools
{
class Program
{
static void Main(string[] args)
{
// Empfängt den Pfad des Ordners, in dem die exe-Datei liegt
string WorkPath = Environment.CurrentDirectory;
// Hier suche ich einen in jedem Fall nicht vorhandenenen Ordner-Namen
string ResultPath = WorkPath + "~";
int i = 1;
// Die Schleife läuft so lange weiter, bis der abgeänderte Pfad nicht existiert.
// Damit die Änderung sich auch ändert, wird eine int-Variable hoch gezählt
while (Directory.Exists(ResultPath + i.ToString())) i++;
// Wenn die Schleife nun endet, speicher ich den neuen Pfad ab und erstelle den Ordner.
ResultPath += i.ToString();
Directory.CreateDirectory(ResultPath);
// Ruft alle Datei-Pfad im angegebenen Ordner ab
string[] files = Directory.GetFiles(WorkPath);
// Hier kommen die ausgemisteten Dateien an, ohne Duplikate
string[] Results = DistinctPictures(files);
// Die Liste der resultierenden Datei-Pfade wird durchlaufen und jede Datei kopiert.
// Der erste Parameter gibt die Quelle, der Zweite das Ziel an
// im zweiten Parameter nehme ich dann den neuen, leeren Ordner-Pfad und hänge auf eine sichere Weise
// Den Datei-Namen an. Dafür gibt es die Methode Path.Combine, die das fehlerfrei erledigt
foreach (var item in Results)
File.Copy(item, Path.Combine(ResultPath, Path.GetFileName(item)));
}
static string[] DistinctPictures(string[] files)
{
// Der Fehler-Text, der in die error.txt geschrieben wird
string ErrorString = "";
var PictureHashList = new byte[files.Length][];
for (int i = 0; i < files.Length; i++)
// Der try-Block wird in jedem Fall ausgeführt
try
{
using (Image img = Image.FromFile(files[i]))
PictureHashList[i] = new SHA256Managed().ComputeHash(
(Byte[])new ImageConverter().ConvertTo(
img, typeof(Byte[])));
}
// Der catch-Block wird immer dann ausgeführt, wenn im try-Block ein Laufzeitfehler auf tritt
catch (Exception ex)
{
// Exception ist die Basis-Klasse für alle Fehler-Klassen.
// Dort kann man verschiedene Typen verwenden und so z.B.
// für die Ableitung "FileNotFoundException" eine gesonderte Fehlerbehandlung einbauen,
// Wenn eine Datei nicht gefunden wurde
// Ich hab hier einfach nur Exception genommen, um den Absturz des Programmes in jedem Fall zu verhindern.
ErrorString += "Error:";
ErrorString += " \r\nDatei: " + files[i];
ErrorString += " \r\nFehler: " + ex.Message;
ErrorString += "\r\n" + new string('-', 20);
}
// Hier schreibe ich die error.txt
// Ein FileStream ist Stream, der geschlossen werden muss, daher verwende ich hier using
// Der Parameter "FileMode.Create" gibt an, dass die Datei entweder erstellt oder überschrieben wird
if (ErrorString != "")
using (FileStream file = new FileStream("error.txt", FileMode.Create))
// Da der FileStream nur Bytes schreiben kann, brauche ich einen StreamWriter,
// der für mich in den FileStream schreibt. Auch der muss danach wieder geschlossen werden,
// daher auch hier wieder using
using (StreamWriter writer = new StreamWriter(file))
writer.Write(ErrorString);
var dictionary = new Dictionary<byte[], string>();
for (int i = 0; i < PictureHashList.Length; i++)
if (PictureHashList[i] != null)
if (!new Func<bool>(() =>
{
foreach (var item in dictionary.Keys.ToList())
if (PictureHashList[i].SequenceEqual(item))
return true;
return false;
}).Invoke())
dictionary.Add(PictureHashList[i], files[i]);
return dictionary.Values.ToArray();
}
}
}