Kopyalanan bir dosyanın orijinal ile aynı olup olmadığını kontrol etmek için her bir baytı okumak gerekli midir?


16

Geçenlerde Total Commander adlı bir program öğrendim. Bu bir Windows Gezgini yedeğidir ve dosyaları kopyalamak için kendi şeylerine sahiptir. Dosyaların aynı olup olmadığını kontrol etmek için, bir CRC hesaplamak yerine, hem orijinal hem de kopyadaki her bir baytı birer birer kontrol eder.

Sorum şu: Bu gerekli mi? CRC veya benzeri herhangi bir teknik yanlış olabilir mi? Bir programcı olarak bu mükemmel ama yavaş sistemi denemeye ve uygulamayı denemelisiniz, yoksa çok mu aşırı?


3
"Rsync" in bunu nasıl ele aldığına bir göz atın.

21
Her iki dosyadaki CRC'leri (veya daha iyisi sha1sums) hesaplamak her baytın yine de okunmasını gerektirir. Bayt byte karşılaştırması yaparsanız, bir uyumsuzluk görür görmez bırakabilirsiniz - ve aynı sağlama toplamına sahip olan iki farklı dosya hakkında endişelenmenize gerek yoktur (ancak sha1sum için bu olası değildir) . Öte yandan, sağlama toplamı karşılaştırmaları aynı makinede olmayan dosyaları karşılaştırırken yararlıdır; sağlama toplamları yerel olarak hesaplanabilir ve tüm içeriği ağ üzerinden aktarmanız gerekmez.
Keith Thompson

3
Çarpışma olasılığına gelince, sizin gibi iyi bir karma kullanırsanız sha1sum, birileri kasıtlı ve pahalı bir şekilde sha1sums çarpışan dosyalar oluşturmazsa , endişelenmenize gerek yoktur . Bunun için bir kaynağım yok, ancak duydum ki (git bağlamında) aynı sha1sum'a sahip iki farklı dosyanın olasılığının, geliştirme ekibinizin her üyesinin yemesi olasılığı ile aynı olduğunu duydum. kurtlar. Aynı günde. Tamamen ilgisiz olaylarda.
Keith Thompson

5
@KeithThompson: Sanırım ilk yorumunuz cevap olmalı :-)
Dean Harding

6
Kısa cevap - Hayır, sadece bilgisayarınızın sizin için yapması en iyisidir.
psr

Yanıtlar:


40

Her iki dosyadaki CRC'leri (veya daha iyisi sha1sums) hesaplamak her baytın yine de okunmasını gerektirir. Bayt byte karşılaştırması yaparsanız, bir uyumsuzluk görür görmez bırakabilirsiniz - ve aynı sağlama toplamına sahip olan iki farklı dosya hakkında endişelenmenize gerek yoktur (ancak sha1sum için bu olası değildir) . Dolayısıyla, karşılaştırmayı yerel olarak yapıyorsanız, bayt byte karşılaştırması en azından sağlama toplamı karşılaştırması kadar hızlı olacaktır (zaten sağlama toplamlarını zaten hesaplamadıysanız).

Öte yandan, sağlama toplamı karşılaştırmaları aynı makinede olmayan dosyaları karşılaştırırken yararlıdır; sağlama toplamları yerel olarak hesaplanabilir ve tüm içeriği ağ üzerinden aktarmanız gerekmez.

Hibrit yaklaşımlar da mümkündür. Örneğin, hesaplamak ve (bütün dosyaları okuma önleyebilirsiniz bir anda iki dosyanın bir yığın, için sağlama karşılaştırmak olabilir eğer onlar farklı) da ağ üzerinden tüm dosyayı iletmek kaçınırken. Rsync protokolü böyle bir şey yapar.

Basit bir CRC kullanmanın, Dave Rager'ın cevabında belirttiği gibi, size bir çarpışma şansı verdiğini unutmayın. En azından sha1sum, hatta daha yeni bir şey kullanın . (Kendi karma algoritmanızı icat etmeye çalışmayın; sha1sum geliştiren insanlar bu şeyler hakkında ikimizden de çok daha fazlasını bilirler.)

Çarpışma olasılığına gelince, sha1sum gibi iyi bir karma kullanırsanız, birileri kasıtlı ve pahalı bir şekilde sha1sums çarpıştığı dosyaları oluşturmadıkça (bu tür çarpışmalar oluşturmak ilk kez yazdığımda mümkün değildi) , ancak ilerleme kaydediliyor ). Aktaran Scott Chacon yönettiği "Pro Git" , bölüm 6.1 :

İşte size bir SHA-1 çarpışması için ne yapılması gerektiğine dair bir fikir vermek için bir örnek. Dünyadaki 6,5 milyar insanın tümü programlıysa ve her saniye, her biri tüm Linux çekirdek geçmişinin (1 milyon Git nesnesi) eşdeğeri olan bir kod üretiyordu ve onu muazzam bir Git deposuna itiyordu, 5 yıl sürecekti havuzun tek bir SHA-1 nesne çarpışması olasılığının% 50 olması için yeterli nesne içermesi. Programlama ekibinizin her üyesinin, aynı gece ilgisiz olaylarda kurtlar tarafından saldırıya uğrayıp öldürülme olasılığı daha yüksektir.

Özet:

Bayt byte karşılaştırması yerel karşılaştırmalar için iyidir. sha1sum uzaktan karşılaştırma için iyidir ve önemli ölçüde yanlış pozitif şansı göstermez.


"İyi" bir hash fonksiyonunun ortak tanımının , aynı hash ("çarpışma direnci") ile farklı girdiler yaratmanın çok zor olduğu özelliği içerdiği unutulmamalıdır . SHA-1'in bu konuda (şimdiye kadar teorik) bazı zayıflıkları vardır, ancak oldukça zor deneseniz bile sadece "çarpışan iki dosya oluşturamazsınız".
sleske

@sleske: Güncellendi
Keith Thompson

1
@KeithThompson Cevabı iptal ediyorum, ancak SHA1 - The SHAppening
K.Steff

GitHub'da bu teorik repoyu barındırmaya çalışırsanız huysuzlaşacaklarından şüpheleniyorum.
hBy2Py

1
Dahası, saniyede çok fazla exabyte veri itme konusunda mutsuz olacakları anlamına geliyordu. :-)
hBy2Py

10

İşte bunu düşünmenin başka bir yolu.

İki farklı dosyanın aynı CRC'ye sahip olma olasılığı yoksa, uzantı ile her dosya benzersiz bir CRC ile temsil edilebilir. CRC orijinal dosyadan daha küçükse, kayıpsız bir sıkıştırma biçimini temsil eder. Değilse, aynı sayıda baytı karşılaştırdığınız için orijinal dosyaları karşılaştırmanız da iyi olur.

Teoride, karşılaştırmada gerekli bayt sayısını azaltmak için karşılaştırmanın her iki tarafının kayıpsız sıkıştırmasını kullanabilirsiniz, ancak bu bir aptal işidir çünkü daha fazla döngü harcar ve sıkıştırmayı yapmak için her iki dosyanın her baytını okumalısınız . Yani, her baytı (ve sırasını) kayıpsız bir sıkıştırma şemasında kodlamak için, önce onu okumanız ve algoritmaya takmanız gerekir, değil mi? Oyun bitti.

İşte bir benzetme:
Basılı iki belgenin harf harf karşılaştırmadan aynı olup olmadığını hızlı bir şekilde belirlemek için bir yol istiyorsanız, belgelerin her satırındaki harf sayısını karşılaştırabilirsiniz. Sayımların tümü eşleşirse, oranlar belgelerin aynı olduğu konusunda önemli ölçüde iyileşir, ancak kimse bu yaklaşımı kullanarak her harfin aynı olduğundan emin olamayacağınızı iddia edemez.


3

Aynı dosyaları kontrol etmenin tek mükemmel yolu bayt karşılaştırması için bayttır. Adil bir yaklaşım olmanın bir başka yolu da dosyalar için MD5 gibi bir karma hesaplamak ve bunları karşılaştırmaktır. Karma bir çarpışma olabilir ama pek olası değil.

Bayt karşılaştırması için bayt karşılaştırma yaparken her iki dosyadaki karma hesaplamak daha hızlı olacağını hayal ediyorum. Ancak, uygulamanız karmayı önceden hesaplar ve dosyalarınızla ilgili meta verileri depolarsa, karmaları karşılaştırmak çok daha hızlı olacaktır.

CRC muhtemelen bir karma değil, sadece bir hata tespit mekanizması olduğu için gitmenin yolu değildir. (veya birçok olası çarpışmaya sahip zayıf bir karma)


+1 Kabul Ediyorum. Soooo, sabit diskinizin iyi karma işlevinin arızi çarpışmasına kıyasla kırılması çok daha muhtemeldir (CRC32 zayıftır - aynı zamanda katılıyorum).
Michał Šrajer

2

% 100 belirli iki dosyanın aynı olması için, baytları gerçekten kontrol etmeniz gerekir.

Neden? Karma çarpışmalar, bu yüzden! Karma için kullanılan algoritmaya bağlı olarak, çarpışma az ya da çok olası olabilir, ancak daha az olasıdır. Aşağıdaki adımları izleyin:

  1. Dosya boyutlarını kontrol edin
  2. MIME tiplerini kontrol edin
  3. Karmayı kontrol et
  4. Birkaç rastgele ofseti kontrol edin ve bitleri karşılaştırın

İki dosyanın aynı olduğuna dair çok yüksek bir güvence verecek, ancak ellerinizde bir çarpışma olması çok (son derece) küçük bir şans var. Karşılaştırmalarınızla ne kadar ileri gitmek istediğinizin seçimi, duruma göre belirlenir.


Eğer iyi bir karma algoritması seçerseniz, 2. ve 4. size herhangi bir gerçek artış "eşit" kalite vermeyeceğini düşünüyorum. Muhtemelen 1. sadece zayıf karma için gereklidir.
Michał Šrajer

1
-1 Bu mantıklı değil. İyi bir karma algoritması seçerseniz, diğer tüm adımlar gereksizdir. 1. ve 4. aslında bir karma'nın zaten yaptığı ve 2. saçmalıktır (Çoğu dosya sistemi "MIME türü" kavramına bile sahip değildir ve sahip olsalar bile, çok az bilgi ekler).
sleske

@sleske Yoğun bir işlem olan dosyayı karma yapmak yerine, çok ağır olmayan bazı ön işlemleri gerçekleştirebilirsiniz.

Sadece 1 ve 3'ü çok anlamlı buluyorum. (1) farklı dosyaların çoğunu, karma değerini hesaplama ihtiyacından tasarruf ederek işaretler. Aynı uzunluktaki dosyadaki karma çatışma, endişelenmeye değmez.
Michael Shaw

1

Diğerlerinin söylediği gibi, iki dosya aynı sistemdeyse bayt bayt karşılaştırması yapmak daha hızlıdır. Bir grup dosyayı karşılaştırmaya çalışıyorsanız, dosyalar depolamayı döndürüyorsa, karma işleminin daha iyi olduğu noktaya ulaşırsınız.

Tüm verilerin hazır olmadığı zaman Hashing gerçekten parlıyor. Örneğin, dosyalar farklı makinelerde. Ayrıca hesaplama sonuçlarını kaydetmenizi ve daha sonra başvurmanızı sağlar. (Bu rapor eskisi ile aynı mı? Raporun bir karmasını kaydetmesini sağladığınızda. Bir sonrakini yaptığınızda sadece karmaları karşılaştırabilirsiniz. Sadece eski raporu okumanıza gerek yok. bunun bir kopyasının olması bile gerekmez.)


0

@Glenn Nelson tarafından özetlenen dosya özelliklerini kontrol ettikten sonra içeriği karşılaştırmak için, sağlanan dosya karşılaştırma yardımcı programını işletim sisteminizle kullanmanız veya bir dosya karşılaştırma aracı (bkz: wiki dosya karşılaştırma araçları ) kullanmanız gerektiğini düşünüyorum.

CRC'nin% 100 doğru olduğunu düşünmüyorum ve dosya uzunluğu ile doğruluğunun azaldığını düşünüyorum. Ayrıca, çok fazla test gerektirebileceğinden sıfırdan yazmanızı önermiyorum.


0

Kopyalanan bir dosyanın orijinal ile aynı olup olmadığını kontrol etmek için her bir baytı okumak gerekli midir? EVET% 100 emin olun

Kopyalanan bir dosyanın orijinal ile aynı OLMADIĞINI kontrol etmek için her bir baytı okumak gerekli midir? HAYIR

Bu nedenle, özdeşliği hızlı bir şekilde belirlemek için, önce dosya boyutu gibi meta verileri ve işletim sisteminin / dosya sisteminin / deposunun zaten koruyabileceği sağlama toplamı / CRC veya MIME türlerini kontrol edin . Bu sistem tarafından önceden hesaplandıkları için, karşılaştırma sırasında bu maliyeti ödemezsiniz.

Bu test başarılı olursa,% 100 emin olmanız gerekiyorsa yine de her baytı ayrı ayrı karşılaştırmanız gerekir, ancak modern boru hatlı CPU'larda ve birden çok iş parçacığı ve muhtemelen birden çok işlemci / CPU kullanmanın büyük dosyaların blok karşılaştırmasının GERÇEKTEN hızlı olduğunu unutmayın. ve verimli çünkü süreç oldukça paralelleştirilebilir. Her bir baytı içeren HERHANGİ bir matematiksel hesaplamadan çok daha hızlıdır (bazı algoritmalar da muhtemelen paralelleştirilebilir, ancak belki de çok kolay veya çok iyi değildir). Bunun nedeni, ardışık düzenlenmiş CPU'ların mikrokodda veya hatta donanımda (gerçekten hızlı) ve diskten belleğe alt sistemlerde bellek blok karşılaştırma işlemlerini yapabilmesidir, hepsi paralel ve birlikte yapılan büyük dosya bloklarını belleğe / belleğe getirmek için oldukça optimize edilmiştir. donanım. Uygulamanız bu tür şeyleri düzenli olarak yapıyorsa ve bilinen bir performans darboğazı varsa, bunu işletim sisteminizin ve donanımınızın paralelleştirme olanaklarından yararlanan iyi yazılmış çok iş parçacıklı kodda uygulamak akıllıca olacaktır (belki de için tasarlanmış bir dil kullanın) bu).

Yalnızca her dosyayı bir kez işlemek ve daha sonra birden fazla karşılaştırma yapmak istiyorsanız (özetlenen ["önbellek") veya "sıkıştırılmış" [JohnFX'in belirttiği gibi] analiz sonucunu hatırladığınız yerde) bunu yapmanın önemli bir yararı olacaktır, ve o zaman bile, sadece farkı kanıtlamak için (muhtemelen); özdeşliği kanıtlamak için, yine de bayt byte karşılaştırması yapmanız gerekir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.