nihil f8d8c4461f Delete command imlpemented
Cancellation
Formatting
2025-05-11 00:19:58 +02:00

147 lines
5.0 KiB
C#

using System.Security.Cryptography;
namespace RedundancyFinder
{
public class Finder
{
public CancellationToken cancellation;
Dictionary<string, Redundancy> redundancies = new Dictionary<string, Redundancy>();
public Dictionary<string, Redundancy> Redundancies { get => redundancies; }
string[] extensions;
List<string> ignorePaths = new List<string>();
public event EventHandler<DirectoryErrorEventArgs>? DirectoryError;
public event EventHandler<FileErrorEventArgs>? FileError;
public event EventHandler<FileFoundEventArgs>? FileFound;
public event EventHandler<string>? TaskStarted;
public event EventHandler<ProcessingFileEventArgs>? ProcessingFile;
public void FindRedundancies(string[] paths, string[] extensions)
{
Redundancies?.Values.SelectMany(x => x.Paths).ToList().ForEach(x => ignorePaths.Add(x));
this.extensions = extensions;
foreach (var path in paths)
{
if (cancellation.IsCancellationRequested)
{
return;
}
if (Directory.Exists(path))
{
ProcessDirectory(path);
}
else if (File.Exists(path))
{
ProcessFile(path);
}
}
}
private void ProcessDirectory(string directoryPath)
{
if (cancellation.IsCancellationRequested)
{
return;
}
try
{
// Process files in the current directory
foreach (var file in Directory.GetFiles(directoryPath))
{
if (cancellation.IsCancellationRequested)
{
return;
}
ProcessFile(file);
}
// Recursively process subdirectories
foreach (var subDirectory in Directory.GetDirectories(directoryPath))
{
if (cancellation.IsCancellationRequested)
{
return;
}
// Check if the directory is hidden and skip it if true
var attributes = File.GetAttributes(subDirectory);
if ((attributes & FileAttributes.Hidden) == FileAttributes.Hidden)
{
continue;
}
try
{
ProcessDirectory(subDirectory);
}
catch (Exception ex)
{
DirectoryError?.Invoke(this, new DirectoryErrorEventArgs() { Exception = ex, Path = subDirectory });
}
}
}
catch (Exception ex)
{
DirectoryError?.Invoke(this, new DirectoryErrorEventArgs() { Exception = ex, Path = directoryPath });
}
}
private void ProcessFile(string filePath)
{
if (cancellation.IsCancellationRequested)
{
return;
}
if (ignorePaths.Contains(filePath))
{
return;
}
if (!extensions.Contains(Path.GetExtension(filePath)))
{
return;
}
//TaskStarted?.Invoke(this, filePath);
//ProcessingFile?.Invoke(this, new ProcessingFileEventArgs() { Path = filePath });
try
{
var fileHash = ComputeFileHash(filePath);
if (fileHash == null)
{
return;
}
long fileSize = new FileInfo(filePath).Length;
lock (Redundancies)
{
if (!Redundancies.ContainsKey(fileHash))
{
var redundancy = new Redundancy() { Hash = fileHash, FileSize = fileSize };
Redundancies.Add(fileHash, redundancy);
}
Redundancies[fileHash].Paths.Add(filePath);
}
FileFound?.Invoke(this, new FileFoundEventArgs(filePath, fileHash, fileSize));
}
catch (Exception ex)
{
FileError?.Invoke(this, new FileErrorEventArgs() { Exception = ex, Path = filePath });
}
}
private static string ComputeFileHash(string filePath)
{
using var sha256 = SHA256.Create();
using var stream = File.OpenRead(filePath);
var hash = sha256.ComputeHash(stream);
return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant();
}
}
}