2014-01-28 53 views
0

我在C#以下情況:哪種方式比較2個文件更好?

ZipFile z1 = ZipFile.Read("f1.zip"); 
ZipFile z2 = ZipFile.Read("f2.zip"); 


MemoryStream ms1 = new MemoryStream(); 
MemoryStream ms2 = new MemoryStream() 


ZipEntry zipentry1 = zip1["f1.dll"]; 
ZipEntry zipentry1 = zip2["f2.dll"]; 


zipentry1.Extract(ms1); 
zipentry2.Extract(ms2); 


byte[] b1 = new byte[ms1.Length]; 
byte[] b2 = new byte[ms2.Length]; 


ms1.Seek(0, SeekOrigin.Begin); 
ms2.Seek(0, SeekOrigin.Begin); 

我在這裏做的是打開2個zip文件f1.zip和f2.zip。然後,我將其中的2個文件(分別在f1.zip和f2.zip中的f1.txt和f2.txt)提取到MemoryStream對象上。我現在想比較這些文件,並確定它們是否相同。我有兩種方法:

1)逐字節讀取內存流並比較它們。 爲此,我會用

ms1.BeginRead(b1, 0, (int) ms1.Length, null, null); 
ms2.BeginRead(b2, 0, (int) ms2.Length, null, null); 

,然後運行一個for循環和B1和B2每個字節進行比較。

2)獲取兩個內存流的字符串值,然後進行字符串比較。對於這個我會使用

string str1 = Encoding.UTF8.GetString(ms1.GetBuffer(), 0, (int)ms1.Length); 
string str2 = Encoding.UTF8.GetString(ms2.GetBuffer(), 0, (int)ms2.Length); 

然後做一個簡單的字符串比較。

現在,我知道逐字節比較將總是給我一個正確的結果。但問題在於,這將需要很長時間,因爲我必須爲數千個文件執行此操作。這就是爲什麼我在考慮字符串比較方法,它會查找文件是否相等或不是很快。但我不確定字符串比較會給我正確的結果,因爲這些文件是dll或媒體文件等,並且肯定會包含特殊字符。

任何人都可以告訴我,如果字符串比較方法可以正常工作嗎?

在此先感謝。

P.S. :我正在使用DotNetLibrary。

+0

字符串比較將比比較字節慢很多。 – Magus

+0

但字節數超過了50000.所以50000以上的循環會比字符串比較慢嗎? – user2945623

+0

@ user2945623不,我敢打賭你的機器會很快完成這個循環,你甚至不會注意到。 –

回答

2

這個問題的基準是比較數組的本地方法:Enumerable.SequenceEqual。除非您有充分理由不這樣做,否則您應該使用它。

如果您關心速度,您可以嘗試在msvcrt.dll中對memcmp進行p/invoke,並以這種方式比較字節數組。我很難想象這會被打敗。顯然,如果兩個字節數組的長度相同,則首先比較長度,只調用memcmp

的的P/Invoke是這樣的:

[DllImport("msvcrt.dll", CallingConvention=CallingConvention.Cdecl)] 
static extern int memcmp(byte[] lhs, byte[] rhs, UIntPtr count); 

但你應該只考慮這一點,如果你真的是速度護理,和純管理的替代品是你太慢了。所以,做一些時機來確保你不會過早地優化。那麼,甚至要確保你正在優化。

如果轉換爲string很快,我會感到非常驚訝。我預計它會很慢。事實上,我希望你的代碼失敗,因爲沒有理由讓你的字節數組成爲有效的UTF-8。忘記你曾經有過這樣的想法!

+0

明白了。非常感謝。 – user2945623

+0

'count'的正確類型是'UIntPtr'。 'ulong'將在32位系統上失敗。 –

+0

@CoryNelson謝謝。你當然是對的。它是'size_t'。不知道發生了什麼。 –

2

比較ZipEntry.CrcZipEntry.UncompressedSize的兩個文件,只有如果它們匹配解壓縮並進行字節比較。如果這兩個文件是相同的,它們的CRC和大小也是一樣的。這一策略將爲您節省大量的CPU週期。

ZipEntry zipentry1 = zip1["f1.dll"]; 
ZipEntry zipentry2 = zip2["f2.dll"]; 

if (zipentry1.Crc == zipentry2.Crc && zipentry1.UncompressedSize == zipentry2.UncompressedSize) 
{ 
    // uncompress 
    zipentry1.Extract(ms1); 
    zipentry2.Extract(ms2); 

    byte[] b1 = new byte[ms1.Length]; 
    byte[] b2 = new byte[ms2.Length]; 

    ms1.Seek(0, SeekOrigin.Begin); 
    ms2.Seek(0, SeekOrigin.Begin); 

    ms1.BeginRead(b1, 0, (int) ms1.Length, null, null); 
    ms2.BeginRead(b2, 0, (int) ms2.Length, null, null); 

    // perform a byte comparison 
    if (Enumerable.SequenceEqual(b1, b2)) // or a simple for loop 
    { 
     // files are the same 
    } 
    else 
    { 
     // files are different 
    } 
} 
else 
{ 
    // files are different 
} 
+0

+1這是非常合理的建議。儘快拒絕不同的文件。 –