In alcune situazioni può capitare la necessità di verificare due file, magari aventi nomi diversi e apparentemente non legati tra loro, per capire se rappresentano la stessa informazione.
Ovviamente la prima cosa che possiamo fare è verificare il loro peso, ovvero la grandezza in KB o MB che occupano i due file su disco, ma questo non è sufficiente per stabilire se effettivamente rappresentano la stessa informazione. Possiamo farlo invece abbastanza facilmente comparando i due file, anche nel caso di file binari, utilizzando un algoritmo di hashing.
Per chi non lo sapesse, un algoritmo di hashing (o di hash) è, detto in maniera semplice, un metodo di trasformazione irreversibile, con il quale una certa informazione viene trasformata in un'altra informazione.
L'informazione originaria, processata e trasformata attraverso un algoritmo di hashing, viene chiamata digest. Dal digest quindi non sarà più possibile risalire al dato da cui è stato generato.

Si tratta di algoritmi matematici molto complessi, che non verranno approfonditi in questa sede, almeno per il momento. Ne esistono di diversi tipi e complessità, ma le caratteristiche che più ci interessano sono:
- il processo non è reversibile (lo abbiamo appena detto);
- la lunghezza del digest è fissa (in funzione dell'algoritmo usato) indipendentemente dalla grandezza dell'informazione originaria;
- il digest è univoco, ovvero non esistono più informazioni originali diverse tra loro che producono lo stesso digest;
- il digest è legato all'informazione originale, ovvero alla stessa informazione originale corrisponde sempre lo stesso digest.
Questa velocissima introduzione su cosa sia un algoritmo di hashing lascia subito intendere che nel mondo informatico questi abbiano trovato una grossa applicabilità, per tanti motivi che non staremo qui a spiegare. Per adesso concentriamo la nostra attenzione sull'ultima caratteristica tra quelle elencate: alla stessa informazione originale corrisponde sempre lo stesso digest.
Potete capire che quindi un algoritmo di hashing può fare proprio al caso nostro. Nell'esempio creiamo un extension method per farlo, ma ovviamente non è strettamente necessario:
public static class Ext { public static bool IsSameFile(this string sFile1, string sFile2) { FileStream fs1 = new FileStream(sFile1, FileMode.Open); FileStream fs2 = new FileStream(sFile2, FileMode.Open); HashAlgorithm hash = HashAlgorithm.Create("MD5"); byte[] baHash1 = hash.ComputeHash(fs1); byte[] baHash2 = hash.ComputeHash(fs2); string sDigest1 = BitConverter.ToString(baHash1); string sDigest2 = BitConverter.ToString(baHash2); bool bFilesAreEqual = sDigest1.Equals(sDigest2); return bFilesAreEqual; } }
Come si vede dal codice, nel nostro semplice esempio, per verificare se due file siano effettivamente identici nel contenuto, utilizziamo due FileStream, uno per ogni file, che ci serviranno ad ospitare appunto il contenuto di questi due files.
FileStream fs1 = new FileStream(sFile1, FileMode.Open); FileStream fs2 = new FileStream(sFile2, FileMode.Open);
Una volta istanziati i due FileStream, possiamo creare una istanza della classe HashAlgoritm, che si occuperà appunto di eseguire gli hash e ottenere un digest a partire da un dato originario.
HashAlgorithm hash = HashAlgorithm.Create("MD5");
Al costruttore di questa classe basta sapere, in forma di stringa, quale algoritmo vogliamo utilizzare (tra quelli disponibili nella classe .NET).
Gli algoritmi che sono disponibili in .NET sono SHA1, MD5, SHA256, SHA384, SHA512.
La lunghezza del digest, come già spiegato prima, è fissata in funzione dell'algoritmo, e ovviamente più lungo sarà il digest da produrre, maggiore sarà il tempo necessario per produrlo.
Chiaramente con il termine "tempo" intendiamo pochi millisecondi o nel peggiore dei casi secondi, che però possono essere rilevanti in caso di operazioni batch.
Nell'esempio verrà usato l'algoritmo MD5, un algoritmo molto veloce. Con questo algoritmo, provvediamo a generare i due Digest, e quindi a confrontarli tra di loro per vedere se sono effettivamente uguali.
string sDigest1 = BitConverter.ToString(baHash1); string sDigest2 = BitConverter.ToString(baHash2); bool bFilesAreEqual = sDigest1.Equals(sDigest2);
In questo modo per comparare due file ci basterà scrivere:
string sFilePath1 = ... string sFilePath2 = ... if (sFilePath1.IsSameFile(sFilePath2)) { ... }
Commenti
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
Approfondimenti
Configurare il nome della run di un workflow di GitHub in base al contesto di esecuzione
Usare i servizi di Azure OpenAI e ChatGPT in ASP.NET Core con Semantic Kernel
Gestire i dati con Azure Cosmos DB Data Explorer
Garantire la provenienza e l'integrità degli artefatti prodotti su GitHub
La gestione della riconnessione al server di Blazor in .NET 9
Referenziare un @layer più alto in CSS
Utilizzare il nuovo modello GPT-4o con Azure OpenAI
Supportare lo HierarchyID di Sql Server in Entity Framework 8
.NET Conference Italia 2024
Aggiornare a .NET 9 su Azure App Service
Recuperare l'ultima versione di una release di GitHub
Usare le navigation property in QuickGrid di Blazor