Eu aprendi recentemente de um programa chamado Total Commander. É uma substituição do Windows Explorer e tem seu próprio material para copiar arquivos. Para verificar se os arquivos são idênticos, em vez de calcular um CRC, ele literalmente verifica cada byte, um de cada vez, no original e na cópia.
Minha pergunta é: isso é necessário? A CRC ou qualquer outra técnica desse tipo pode dar errado? Como programador, você deve tentar implementar esse sistema perfeito, mas lento, ou é muito extremo?
difference
file-handling
Koen027
fonte
fonte
sha1sum
você, não precisa se preocupar com isso, a menos que alguém esteja deliberada e dispendiosamente construindo arquivos cujos sha1sums colidem. Eu não tenho uma fonte para isso, mas ouvi (no contexto do git) que a probabilidade de dois arquivos diferentes terem o mesmo sha1sum é quase a mesma que a probabilidade de cada membro de sua equipe de desenvolvimento ser comido por Lobos. No mesmo dia. Em incidentes completamente não relacionados.Respostas:
O cálculo de CRCs (ou, melhor, sha1sums) nos dois arquivos requer a leitura de todos os bytes. Se você fizer uma comparação de byte a byte, poderá sair assim que encontrar uma incompatibilidade - e não precisará se preocupar com dois arquivos diferentes que possuam a mesma soma de verificação (embora isso seja improvável para sha1sum) . Portanto, se você estiver fazendo a comparação localmente, uma comparação de byte a byte será pelo menos tão rápida quanto uma comparação de soma de verificação (a menos que você já tenha calculado as somas de verificação de qualquer maneira).
Por outro lado, as comparações de soma de verificação são úteis quando você está comparando arquivos que não estão na mesma máquina; as somas de verificação podem ser calculadas localmente e você não precisa transferir todo o conteúdo pela rede.
Abordagens híbridas também são possíveis. Por exemplo, você pode calcular e comparar somas de verificação para os dois arquivos um pedaço de cada vez, o que pode evitar a leitura dos arquivos inteiros ( se eles diferirem) e também a transmissão do arquivo inteiro pela rede. O protocolo rsync faz algo assim.
Observe que o uso de um CRC simples oferece uma boa chance de colisão, como Dave Rager mencionou em sua resposta. Use pelo menos sha1sum ou mesmo algo mais recente. (Não tente inventar seu próprio algoritmo de hash; as pessoas que desenvolveram sha1sum sabem muito mais sobre isso do que qualquer um de nós.)
Quanto à probabilidade de colisão, se você usa um hash decente como sha1sum, não precisa se preocupar com isso, a menos que alguém esteja construindo deliberada e dispendiosamente arquivos cujos sha1sums colidem (gerar essas colisões não era viável quando escrevi pela primeira vez isso. , mas está sendo feito progresso ). Citando o "Pro Git" de Scott Chacon , seção 6.1 :
Resumo:
A comparação byte a byte é boa para comparações locais. O sha1sum é bom para comparação remota e não apresenta chance significativa de falsos positivos.
fonte
Aqui está outra maneira de pensar sobre isso.
Se não houver possibilidade de que dois arquivos diferentes tenham o mesmo CRC, por extensão, significa que cada arquivo pode ser representado por um único CRC. Se o CRC for menor que o arquivo original, isso representará uma forma de compactação sem perdas. Caso contrário, você faria o mesmo para comparar os arquivos originais, pois compararia o mesmo número de bytes.
Em teoria, você poderia usar a compactação sem perdas de ambos os lados da comparação para reduzir o número de bytes necessários na comparação, mas é uma tarefa tola, porque você gastaria mais ciclos e teria que ler todos os bytes dos dois arquivos para fazer a compactação . Ou seja, para codificar cada byte (e sua ordem) em um esquema de compactação sem perdas, é necessário primeiro lê-lo e conectá-lo ao algoritmo, certo? Fim de jogo.
Aqui está uma analogia:
se você quisesse determinar rapidamente se dois documentos impressos eram idênticos sem comparar letra por letra, você poderia comparar a contagem de letras em cada linha dos documentos. Se todas as contagens corresponderem, as chances aumentam substancialmente de que os documentos sejam idênticos; no entanto, ninguém argumentaria que você poderia ter certeza de que todas as letras eram iguais usando essa abordagem.
fonte
A única maneira perfeita de verificar arquivos idênticos é o byte para comparação de bytes. Outra maneira de ser uma aproximação justa é calcular um hash como MD5 para os arquivos e compará-los. É possível que haja uma colisão de hash, mas não é muito provável.
Eu imagino que a comparação de bytes por byte seria mais rápida do que calcular o hash nos dois arquivos no momento em que você está fazendo a comparação. No entanto, se seu aplicativo pré-calcular o hash e armazenar metadados sobre seus arquivos, a comparação de hashes será significativamente mais rápida.
Provavelmente, o CRC não é o caminho a seguir, pois é apenas um mecanismo de detecção de erros, não um hash. (ou um hash ruim com muitas possíveis colisões)
fonte
Para ter 100% de certeza de que dois arquivos são idênticos, você realmente precisa verificar os bytes.
Por quê? Colisões hash, é por isso! Dependendo do algoritmo usado para o hash, a colisão pode ser mais ou menos provável, mas é possível. Seguindo estas etapas:
Dará a você uma garantia muito alta de certeza de que os dois arquivos são os mesmos, no entanto, há uma chance muito (extremamente) pequena de você ter uma colisão em suas mãos. A escolha de quão longe você deseja ir com suas comparações será ditada pela situação.
fonte
Como outros já disseram, é mais rápido fazer uma comparação byte a byte se os dois arquivos estiverem no mesmo sistema. Se você estiver tentando comparar vários arquivos, chegará ao ponto em que o hash é a melhor resposta se os arquivos estiverem no armazenamento giratório.
O hash realmente brilha quando você não tem todos os dados disponíveis. Por exemplo, os arquivos estão em máquinas diferentes. Também permite salvar os resultados dos cálculos e consultá-los mais tarde. (Este relatório é o mesmo que o antigo? Quando você faz o relatório salvar um hash. Quando você faz o próximo, você pode simplesmente comparar os hashes. Além de não precisar ler o antigo, não nem precisa ter uma cópia disponível.)
fonte
Eu acho que você deve usar o utilitário de comparação de arquivos fornecido com o sistema operacional ou uma ferramenta de comparação de arquivos (consulte: ferramentas de comparação de arquivos wiki ) para comparar o conteúdo DEPOIS de verificar as propriedades do arquivo descritas por @ Nelson Nelson.
Não acho que a CRC seja 100% precisa e acho que sua precisão diminui com o tamanho do arquivo. Além disso, não sugiro que você escreva do zero, pois pode exigir muitos testes.
fonte
É necessário ler todos os bytes para verificar se um arquivo copiado é idêntico ao original? SIM para ter 100% de certeza
É necessário ler todos os bytes para verificar se um arquivo copiado NÃO é idêntico ao original? NÃO
Portanto, para determinar rapidamente a não-identidade, verifique primeiro metadados como tamanho do arquivo e qualquer tipo de soma de verificação / CRC ou MIME que o sistema operacional / sistema de arquivos / armazenamento já possa estar mantendo . Como eles são pré-calculados por esse sistema, você não paga esse custo no momento da comparação.
Se esse teste for aprovado, você ainda precisará comparar todos os bytes individualmente, se precisar de 100% de certeza, mas observe que em CPUs modernas com pipeline e usando vários threads e possivelmente vários processadores / CPUs, a comparação de blocos de arquivos grandes é MUITO rápida. e eficiente porque o processo é altamente paralelelizável. Muito mais rápido do que QUALQUER tipo de computação matemática envolvendo cada byte (embora alguns algoritmos também sejam paralelamente possíveis, mas talvez não tão facilmente ou tão bem). Isso porque as CPUs com pipeline podem realizar operações de comparação de blocos de memória em microcódigo ou mesmo hardware (muito rápido) e subsistemas de disco para memória são altamente otimizados para trazer grandes blocos de arquivos para / da memória, todos feitos em paralelo e com hardware. Se seu aplicativo faz esse tipo de coisa regularmente, e é um gargalo de desempenho conhecido, você deve implementá-lo em código multithread bem escrito que aproveita os recursos de paralelização de seu sistema operacional e hardware (talvez use uma linguagem projetada para esta).
Somente se você desejar processar cada arquivo uma vez e fazer várias comparações posteriormente (em que você lembra ["armazenar em cache"] o resultado da análise resumida ou "compactada" [como diz JohnFX]]), haverá um benefício significativo em fazê-lo, e mesmo assim, apenas para provar a diferença (provável); para provar a identidade, você ainda precisará fazer a comparação byte a byte.
fonte