web-dev-qa-db-ja.com

コピーされたファイルが元のファイルと同一であるかどうかを確認するために、すべての1バイトを読み取る必要がありますか?

最近、Total Commanderというプログラムを知りました。これはWindows Explorerの代替品であり、ファイルをコピーするための独自のものがあります。 CRCを計算する代わりに、ファイルが同一であるかどうかをチェックするために、元のファイルとコピーの両方で、文字ごとに一度に1バイトずつチェックします。

私の質問は、これは必要ですか? CRCまたは他のそのような技術はうまくいかないのでしょうか?プログラマとして、この完璧だが遅いシステムを試して実装する必要がありますか、それとも極端ですか?

16
Koen027

両方のファイルのCRC(またはより適切には、sha1sums)を計算するには、とにかくすべてのバイトを読み取る必要があります。バイトごとの比較を行う場合、不一致が見つかればすぐに終了できます。また、同じチェックサムを持つ2つの異なるファイルについて心配する必要はありません(sha1sumの場合はほとんどありません)。 。したがって、ローカルで比較を行う場合、バイト単位の比較は、少なくともチェックサム比較と同じくらい高速になります(とにかくチェックサムを計算していない限り)。

一方、チェックサム比較は、同じマシン上にないファイルを比較する場合に役立ちます。チェックサムはローカルで計算できるため、コンテンツ全体をネットワーク経由で転送する必要はありません。

ハイブリッドアプローチも可能です。たとえば、2つのファイルのチェックサムを一度にチャンクで計算して比較すると、ファイル全体の読み取りを回避しながら(ifif(---))ファイル全体の送信を回避できます。ネットワーク全体。 rsync protocol はこのようなことをします。

単純なCRCを使用すると、Dave Ragerが回答で述べたように、衝突の可能性がかなり高くなります。 少なくともsha1sum、あるいはもっと最近のものを使用してください。 (独自のハッシュアルゴリズムを発明しようとしないでください。sha1sumを開発した人々は、このことについて私たちのどちらよりもはるかに多く知っています。)

衝突の可能性については、sha1sumのようなまともなハッシュを使用する場合、誰かが故意に高価にsha1sumが衝突するファイルを構築していない限り、ほとんど心配する必要はありません。 (そのような衝突の生成は 実現不可能 でしたが、これを最初に書いたときは 進行中 )。引用 Scott Chaconの "Pro Git"セクション6.1

SHA-1の衝突が発生するまでに何が必要かを理解するための例を次に示します。地球上の65億人すべてがプログラミングを行っており、毎秒、Linuxカーネル履歴全体(100万Gitオブジェクト)に相当するコードを生成し、それを1つの巨大なGitリポジトリーにプッシュすると、5年かかります。そのリポジトリには、単一のSHA-1オブジェクトの衝突の50%の確率を持つ十分なオブジェクトが含まれていました。同じ夜に関係のない事件で、プログラミングチームのすべてのメンバーがオオカミに攻撃されて殺される可能性が高くなります。

概要:

バイトごとの比較は、ローカル比較に適しています。 sha1sumはリモート比較に適しており、誤検知の可能性はほとんどありません。

40
Keith Thompson

これについて考える別の方法があります。

2つの異なるファイルが同じCRCを持つ可能性がない場合、拡張により、すべてのファイルを一意のCRCで表すことができることを意味します。CRCが元のファイルよりも小さい場合は、可逆圧縮の形式を表します。そうでない場合は、同じバイト数を比較するため、元のファイルを比較することも同様に行います。

理論的には、比較の両側でロスレス圧縮を使用して、比較に必要なバイト数を減らすことができますが、より多くのサイクルを無駄にし、両方のファイルのすべてのバイトを読み取って圧縮を行う必要があるため、これはばかげた用事です。つまり、すべてのバイト(およびその順序)をロスレス圧縮スキームでエンコードするには、まずそれを読み込んでアルゴリズムにプラグインする必要がありますよね?ゲームオーバー。

これは類推です:
2つの印刷ドキュメントが文字ごとに比較することなく同一かどうかをすばやく判断する方法が必要な場合は、ドキュメントの各行の文字数を比較できます。カウントがすべて一致した場合、オッズはドキュメントが同一であることを大幅に改善しますが、このアプローチを使用すると、すべての文字が同じであると確信することはできません。

10
JohnFx

同一ファイルをチェックする唯一の完璧な方法は、バイトごとの比較です。公平に近似するもう1つの方法は、ファイルのMD5などのハッシュを計算し、それらを比較することです。ハッシュの衝突が発生する可能性はありますが、可能性は低いです。

バイト比較のためのバイトは、比較を行っているときに両方のファイルのハッシュを計算するよりも速くなると思います。ただし、アプリケーションがハッシュを事前に計算してファイルに関するメタデータを保存している場合は、ハッシュの比較が大幅に速くなります。

CRCは、エラー検出メカニズムであり、ハッシュではないため、おそらく適切な方法ではありません。 (または可能性のある衝突がたくさんある貧弱なハッシュ)

3
Dave Rager

100%であることを確実にするために、2つのファイルが同一であることを確認するには、実際にバイトを確認する必要があります。

どうして?ハッシュ衝突、それが理由です!ハッシュに使用されるアルゴリズムに応じて、衝突の可能性は多かれ少なかれありますが、それでもなお可能です。次の手順に従います。

  1. ファイルサイズを確認する
  2. MIMEタイプを確認する
  3. ハッシュをチェック
  4. いくつかのランダムなオフセットを確認し、ビットを比較します

2つのファイルが同じであることの確実性が非常に高くなりますが、手に衝突する可能性は非常に(非常に)小さいです。比較をどの程度行うかは、状況によって決まります。

2
user7007

他の人が言ったように、2つのファイルが同じシステム上にある場合、バイトごとの比較を行う方が高速です。大量のファイルを比較しようとしている場合、ファイルが回転ストレージ上にある場合、ハッシュがより良い答えになるポイントに到達します。

すべてのデータをすぐに利用できない場合、ハッシュは本当に有効です。たとえば、ファイルが異なるマシン上にあります。また、計算結果を保存して後で参照することもできます。 (このレポートは古いレポートと同じですか?レポートにハッシュを保存させます。次のレポートを作成するときに、ハッシュを比較するだけです。古いものを読む必要がないだけでなく、コピーを用意する必要さえあります。)

1
Loren Pechtel

提供されているファイル比較ユーティリティをオペレーティングシステムで使用するか、ファイル比較ツール( wiki-file compare tools を参照)を使用して内容を比較する必要があると思います。グレン・ネルソン。

CRCは100%正確であるとは思いません。また、CRCはファイルの長さによって精度が低下すると思います。また、多くのテストが必要になる可能性があるため、最初から作成することはお勧めしません。

0
NoChance

コピーされたファイルが元のファイルと同一であるかどうかを確認するために、すべての1バイトを読み取る必要がありますか?はい、100%確実です

コピーされたファイルが元のファイルと同一でないかどうかを確認するために、すべての1バイトを読み取る必要がありますか?番号

したがって、非同一性を迅速に判断するには、まずファイルサイズなどのメタデータと、OS/file-system/storeのチェックサム/ CRCまたはMIMEタイプすでに維持中を確認します。それらはそのシステムによって事前に計算されているため、比較時にこのコストを支払う必要はありません。

そのテストに合格した場合でも、100%の確実性が必要な場合は、各バイトを個別に比較する必要がありますが、最新のパイプライン化されたCPUでは、複数のスレッドと、場合によっては複数のプロセッサ/ CPUを使用するため、大きなファイルのブロック比較は非常に高速です。プロセスが高度に並列化可能であるため、効率的です。各バイトを含むあらゆる種類の数学的計算よりもはるかに高速です(一部のアルゴリズムは並列化も可能ですが、それほど簡単ではないかもしれません)。これは、パイプライン処理されたCPUがマイクロコードまたはハードウェア(非常に高速)のメモリのブロック比較操作を実行でき、ディスクからメモリへのサブシステムが非常に最適化されているため、メモリとの間でファイルの巨大なブロックをすべて並行して実行できます。ハードウェア。アプリケーションがこの種のことを定期的に行い、それが既知のパフォーマンスのボトルネックである場合、OSとハードウェアの並列化機能を利用する適切に記述されたマルチスレッドコードでこれを実装することをお勧めします(おそらく、この)。

各ファイルを1回処理し、後で複数の比較を実行する場合(「[キャッシュ」]の要約、または「圧縮」[JohnFXによる分析]の分析結果を覚えている場合)のみ、そうすることには大きなメリットがあります。そしてそれでも、違いを証明するためだけに(おそらく);同一性を証明するには、バイトごとの比較を行う必要があります。

0
user14517