Comparação de Pdf

6 respostas
D

Pessoal,

estou precisando realizar uma comparação entre arquivos pdf em meu sistema, pois o usuário não pode anexar o mesmo arquivo 2 vezes.
Uma comparação muito ruim seria pelo nome do arquivo, mas vai que o usuário renomeia o arquivo e acaba anexando ele denovo, ai essa comparação por novo já não iria funcionar, barraria somente alguns arquivos.

6 Respostas

E

Você não quer que o mesmo arquivo (binariamente falando) seja anexado 2 vezes? (Ou seja, você pode anexar uma versão mais nova, ligeiramente modificada do PDF)?

Se for assim, é relativamente simples. Calculer o MD5 ou o SHA-1 do arquivo e guarde esse valor. Se porventura o usuário quiser anexar EXATAMENTE O MESMO arquivo (mesmo que com nome diferente), o MD5 ou SHA-1 vai bater, e então nesse caso você não deixa. Se mudar um byte que seja, o MD5 ou SHA-1 não vai bater.

D

Exatamente, não quero que o mesmo arquivo seja anexado 2 vezes.
Não entendi direito isso:

Acho que se o arquivo está levemente modificado, o usuário não precisaria anexar este outro documento.

De qualquer forma, como que eu faria pra calcular esse MD% ou SHA-1 dos arquivos?

E

É que é muito mais difícil você saber se um arquivo foi ligeiramente modificado, e se essa alteração é significativa ou não (por exemplo, um texto tinha “R$99,99” e agora tem “R$99,98” - uma alteração de tabela de preços, por exemplo), que simplesmente fazer uma comparação binária.
Fazer uma comparação binária é muito simples.

D

Entendi,

bom acho que se o ducumento foi levemente modificado não iria ter problema, então ele poderia anexar este documento.
Neste caso teria que calcular o MD5 ou SHA-1 de cada arquivo pra ver se eles batem.
Como faço esta verificação? Existe algum exemplo aqui no forum pra eu pegar como base?

E

Bom…
Aqui vai um exemplo (para eu não anexar um arquivo de teste aqui, eu simplesmente crio o arquivo só para você poder ver como é que funciona).

import java.io.*;
import java.util.*;
import java.security.*;

class CalcularHashArquivo {

    private static String hex (byte[] bytes) {
        StringBuilder sb = new StringBuilder (bytes.length * 2);
        Formatter fmt = new Formatter (sb);
        for (int i = 0; i < bytes.length; ++i) {
            fmt.format ("%02X", bytes[i] & 0xFF);
        }
        return sb.toString();
    }

    // Este método faz o cálculo do MD5, SHA1 etc. de um arquivo qualquer. 
    public static String calcular (File nomeArquivo, MessageDigest md) throws IOException {
        md.reset();
        DigestInputStream dis = new DigestInputStream (new BufferedInputStream (new FileInputStream (nomeArquivo)), md);
        byte[] bytes = new byte[8 * 1024];
        while (dis.read(bytes) > 0) {
            ;
        }
        dis.close();
        byte[] digest = md.digest();
        return hex (digest);
    }
    
    // Teste
    public static void main (String[] args) throws Exception {
        // Aqui vamos usar o MD5, mas podemos usar um outro hash, como o SHA-1. Basta mudar o argumento
        MessageDigest md = MessageDigest.getInstance ("MD5");
        // Criando um arquivo de teste de 1MB - tamanho típico para um PDF
        // Só para ficar mais interessante, vou criar com dados aleatórios
        // (em vez de deixar cheio de zeros).
        Random r = new Random (1234L); // pus 1234L para forçar a gerar dados "aleatórios" mas conhecidos
        File f = new File ("teste.bin");
        FileOutputStream fos = new FileOutputStream (f);
        byte[] bytes = new byte[1024 * 1024];
        r.nextBytes (bytes); // isto preenche com 1 MB de dados aleatórios
        fos.write (bytes);
        fos.close();
        // Calculando o MD5 e o imprimindo
        String md5_arquivo1 = CalcularHashArquivo.calcular (f, md);
        System.out.println (md5_arquivo1); // imprime 00EBBF29153FEF4EB5E4A9E48C8AA87F
        // Agora criando um arquivo igualzinho
        f = new File ("teste2.bin");
        fos = new FileOutputStream (f);
        fos.write (bytes);
        fos.close();
        String md5_arquivo2 = CalcularHashArquivo.calcular (f, md);
        System.out.println (md5_arquivo2); // imprime 00EBBF29153FEF4EB5E4A9E48C8AA87F
        // Agora criando um arquivo que tem apenas 1 bit de diferença, na posição 500000
        // Veja que o valor vai dar completamente diferente. 
        f = new File ("teste3.bin");
        bytes[500000] ^= 0x01; // isso mexe em apenas 1 bit
        fos = new FileOutputStream (f);
        fos.write (bytes);
        fos.close();
        String md5_arquivo3 = CalcularHashArquivo.calcular (f, md);
        System.out.println (md5_arquivo3); // imprime B46B2696D997EA2C436FAEBB129354B0
    }
}
D

ok,

valeu pela ajuda.

Vou testar aqui assim que tiver um tempinho.

flw

Criado 28 de outubro de 2010
Ultima resposta 28 de out. de 2010
Respostas 6
Participantes 2