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.
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
dempbr
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
entanglement
É 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
dempbr
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
entanglement
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).
importjava.io.*;importjava.util.*;importjava.security.*;classCalcularHashArquivo{privatestaticStringhex(byte[]bytes){StringBuildersb=newStringBuilder(bytes.length*2);Formatterfmt=newFormatter(sb);for(inti=0;i<bytes.length;++i){fmt.format("%02X",bytes[i]&0xFF);}returnsb.toString();}// Este método faz o cálculo do MD5, SHA1 etc. de um arquivo qualquer. publicstaticStringcalcular(FilenomeArquivo,MessageDigestmd)throwsIOException{md.reset();DigestInputStreamdis=newDigestInputStream(newBufferedInputStream(newFileInputStream(nomeArquivo)),md);byte[]bytes=newbyte[8*1024];while(dis.read(bytes)>0){;}dis.close();byte[]digest=md.digest();returnhex(digest);}// Testepublicstaticvoidmain(String[]args)throwsException{// Aqui vamos usar o MD5, mas podemos usar um outro hash, como o SHA-1. Basta mudar o argumentoMessageDigestmd=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).Randomr=newRandom(1234L);// pus 1234L para forçar a gerar dados "aleatórios" mas conhecidosFilef=newFile("teste.bin");FileOutputStreamfos=newFileOutputStream(f);byte[]bytes=newbyte[1024*1024];r.nextBytes(bytes);// isto preenche com 1 MB de dados aleatóriosfos.write(bytes);fos.close();// Calculando o MD5 e o imprimindoStringmd5_arquivo1=CalcularHashArquivo.calcular(f,md);System.out.println(md5_arquivo1);// imprime 00EBBF29153FEF4EB5E4A9E48C8AA87F// Agora criando um arquivo igualzinhof=newFile("teste2.bin");fos=newFileOutputStream(f);fos.write(bytes);fos.close();Stringmd5_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=newFile("teste3.bin");bytes[500000]^=0x01;// isso mexe em apenas 1 bitfos=newFileOutputStream(f);fos.write(bytes);fos.close();Stringmd5_arquivo3=CalcularHashArquivo.calcular(f,md);System.out.println(md5_arquivo3);// imprime B46B2696D997EA2C436FAEBB129354B0}}