2011-03-09 62 views
1

我嘗試使用逐字節比較,並比較文件的計算散列(代碼示例如下)。我有一個文件,複製它 - 比較兩個 - 結果是TRUE。但是,當我打開其中一個文件時,問題就開始了:比較2個文件時出現問題 - false應該是true?

MS字文件 - 在打開和關閉其中一個文件後,結果仍爲TRUE,但是,例如,當我刪除文件中的最後一個符號時,再次,然後嘗試再次比較 - 結果FALSE。文件基本上是一樣的,理論上說,似乎在逐字節他們不再是相同的。

使用Excel文件 - 即使打開文件也會導致函數返回false。它應該是那樣嗎?只有我能想到的事情發生了變化,就是Last Access時間。但在比較逐字節時是否考慮到了這一點?

所以我想問一下,這個比較是否應該像這樣工作,我有什麼辦法可以避免這種情況?在我的程序中,我將比較mostly.pdf文件,其中編輯將不是一個很好的選擇,但我仍然想知道爲什麼它會像這樣。

逐字節與緩衝:

static bool FilesAreEqualFaster(string f1, string f2) 
    { 
     // get file length and make sure lengths are identical 
     long length = new FileInfo(f1).Length; 
     if (length != new FileInfo(f2).Length) 
      return false; 

     byte[] buf1 = new byte[4096]; 
     byte[] buf2 = new byte[4096]; 

     // open both for reading 
     using (FileStream stream1 = File.OpenRead(f1)) 
     using (FileStream stream2 = File.OpenRead(f2)) 
     { 
      // compare content for equality 
      int b1, b2; 
      while (length > 0) 
      { 
       // figure out how much to read 
       int toRead = buf1.Length; 
       if (toRead > length) 
        toRead = (int)length; 
       length -= toRead; 

       // read a chunk from each and compare 
       b1 = stream1.Read(buf1, 0, toRead); 
       b2 = stream2.Read(buf2, 0, toRead); 
       for (int i = 0; i < toRead; ++i) 
        if (buf1[i] != buf2[i]) 
         return false; 
      } 
     } 

     return true; 
    } 

哈希:

private static bool CompareFileHashes(string fileName1, string fileName2) 
    { 
     // Compare file sizes before continuing. 
     // If sizes are equal then compare bytes. 
     if (CompareFileSizes(fileName1, fileName2)) 
     { 
      // Create an instance of System.Security.Cryptography.HashAlgorithm 
      HashAlgorithm hash = HashAlgorithm.Create(); 

      // Declare byte arrays to store our file hashes 
      byte[] fileHash1; 
      byte[] fileHash2; 

      // Open a System.IO.FileStream for each file. 
      // Note: With the 'using' keyword the streams 
      // are closed automatically. 
      using (FileStream fileStream1 = new FileStream(fileName1, FileMode.Open), 
           fileStream2 = new FileStream(fileName2, FileMode.Open)) 
      { 
       // Compute file hashes 
       fileHash1 = hash.ComputeHash(fileStream1); 
       fileHash2 = hash.ComputeHash(fileStream2); 
      } 

      return BitConverter.ToString(fileHash1) == BitConverter.ToString(fileHash2); 
     } 
     else 
     { 
      return false; 
     } 
    } 
+0

當然,如果你編輯文件,他們只是「基本相同」,那麼他們是不一樣的,結果應該是錯誤的... – Rob 2011-03-09 10:01:00

+0

事情是,他們幾乎是相同的 - 我只是刪除一個simbol和然後將其寫回並保存 - 上下文,格式,一切都是一樣的,但在字節級別,它們變得不同。我想我會忍受這一點,因爲我只需要比較.pdf文件,這似乎不那麼敏感。 – andree 2011-03-09 10:22:07

回答

2
從別的

除此之外,這個代碼是錯誤的:

b1 = stream1.Read(buf1, 0, toRead); 
b2 = stream2.Read(buf2, 0, toRead); 
for (int i = 0; i < toRead; ++i) 
    if (buf1[i] != buf2[i]) 
     return false; 

你忽略b1b2彼此不相等的可能性以及toRead。如果您只需要讀取第一個數據流中的10個字節和第二個數據中的20個字節,那麼當您要求30個字節時呢?您可能沒有達到文件的結尾,但它仍然可能會使您返回的數據少於您的要求。 千萬不要忽略Stream.Read的返回值。 (你將它保存在一個變量中,但忽略變量。)

基本上你需要有獨立的緩衝區,必要時補充 - 跟蹤你在每個緩衝區內的位置以及多少有用的數據在那裏。在需要時將更多數據讀入每個緩衝區。

再就是文件實際上打開它們,亨克提到的只是改變的其他問題。