2011-06-17 14 views
8

Sto facendo un po 'di codice per l'elaborazione delle immagini, in cui ho scaricato alcune immagini (come BufferedImage) dagli URL e l'ho passato a un processore di immagini.Per verificare se due file di immagine sono uguali. Checksum o Hash?

Desidero evitare di passare la stessa immagine più di una volta al processore di immagini (poiché l'operazione di elaborazione dell'immagine è di costo elevato). Gli endpoint URL delle immagini (se sono le stesse immagini) possono variare e quindi posso impedirlo dall'URL. Quindi stavo pianificando di fare un checksum o un hash per identificare se il codice sta incontrando di nuovo la stessa immagine.

Per md5 ho provato Fast MD5 e ha generato un valore di checksum esadecimale di lunghezza caratteri 20K + per l'immagine (alcuni esempi). Ovviamente la memorizzazione di questo hash di caratteri 20K + sarebbe un problema quando si tratta di archiviazione del database. Quindi ho provato il CRC32 (da java.util.zip.CRC32). E ha generato una somma di controllo di lunghezza piuttosto ridotta rispetto all'hash.

Comprendo il checksum e l'hash per scopi diversi. Per lo scopo sopra spiegato posso semplicemente usare il CRC32? Potrebbe risolvere lo scopo o devo provare qualcosa di più di questi due?

Grazie, Abi

+1

[Il checksum e la somma di hash sono uguali] (http://en.wikipedia.org/wiki/Checksum). In realtà basta guardare diversi algoritmi. –

+1

L'hash MD5 a 128 bit dovrebbe essere sufficiente per il tuo scopo. – Thor

+5

BTW - MD5 dovrebbe creare un valore hash a 128 bit mentre un crc32 ha 32 bit ... Che cosa hai fatto per generare checksum esadecimali di lunghezza 20k +? –

risposta

1

Un checksum e un hash sono sostanzialmente gli stessi. Dovresti essere in grado di calcolare qualsiasi tipo di hash. Un normale MD5 sarebbe normalmente sufficiente. Se vuoi, puoi memorizzare la dimensione e l'hash md5 (che è 16 byte, penso).

Se due file hanno dimensioni diverse, sono file diversi. Non avrai nemmeno bisogno di calcolare un hash sui dati. Se è improbabile che tu abbia molti file duplicati, e che i file siano di un tipo più grande (come le immagini JPG scattate con una macchina fotografica), questa ottimizzazione potrebbe risparmiare un sacco di tempo.

Se due o più file hanno le stesse dimensioni, è possibile calcolare gli hash e confrontarli.

Se due hash sono uguali, è possibile confrontare i dati effettivi per vedere se questo è diverso dopo tutto. Questo è molto, molto improbabile, ma teoricamente possibile. Più grande è il tuo hash (md5 è 16 byte, mentre CR32 è solo 4), meno probabile che due file diversi abbiano lo stesso hash. Ci vorranno solo 10 minuti di programmazione per eseguire questo controllo extra, quindi direi: meglio prevenire che curare. :)

Per ottimizzare ulteriormente questo, se esattamente due file hanno le stesse dimensioni, è sufficiente confrontare i loro dati. Dovrai comunque leggere i file per calcolare i loro hash, quindi perché non confrontarli direttamente se sono gli unici due con quella specifica dimensione.

+0

Forse potrebbe esserci un problema con la memorizzazione dei file già elaborati per confrontarli con quelli nuovi Un checksum o un hash richiedono meno spazio. – SJuan76

+0

È vero. Non ho mai voluto memorizzare l'intero file nel database per il confronto. Solo dicendo che per una singola esecuzione, non sarebbe necessario calcolare un hash del tutto. archiviare i dati per controllare i nuovi file aggiunti, quindi ha senso memorizzare un hash, oppure è possibile scegliere di memorizzare solo le dimensioni del file e calcolare (e memorizzare) l'hash solo se due file sono es match. Ciò consente di risparmiare spazio e di salvare il disco IO. – GolezTrol

5

La differenza tra CRC e, ad esempio, MD5, è che è più difficile manomettere un file in modo che corrisponda a un MD5 "target" piuttosto che manometterlo per corrispondere a un checksum "target". Poiché questo non sembra un problema per il tuo programma, non dovrebbe importare quale metodo usi. Forse MD5 potrebbe essere un po 'più impegnativo per la CPU, ma non so se quello diverso sarà importante.

La domanda principale deve essere il numero di byte del digest.

Se si sta eseguendo un checksum in un intero, significa che per un file di dimensione 2K si stanno adattando 2^2048 combinazioni in 2^32 combinazioni -> per ogni valore CRC, si avrà 2^64 possibili file corrispondenti. Se hai un MD5 a 128 bit, allora hai 2^16 possibili collisioni.

Più grande è il codice che si calcola, minori sono le collisioni possibili (dato che i codici calcolati sono distribuiti in modo uniforme), quindi è più sicuro il confronto.

In ogni caso, al fine di ridurre al minimo possibili errori, penso che la prima classificazione dovrebbe essere l'utilizzo della dimensione del file ... prima confrontare le dimensioni dei file, se corrispondono corrispondono quindi a checksum/hash.

-3

per confrontare due immagini bufferizzate è possibile utilizzare BufferedImage.equals() e per semplicità è possibile utilizzare BufferedImage.hashCode() per ottenere l'hash dell'immagine in modo rapido e veloce.

+6

Entrambi 'equals()' e 'hashCode()' ricadono sull'implementazione predefinita 'Object' e non possono essere usati per confrontare due diverse istanze di' BufferedImage's –

Problemi correlati