[英]Which is a better way to compare 2 files?
我在C#中有以下情況:
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或媒體文件等,並且肯定包含特殊字符。
誰能告訴我字符串比較方法是否可以正常工作?
提前致謝。
PS:我正在使用DotNetLibrary。
此問題的基線是比較數組的本機方法: Enumerable.SequenceEqual
。 除非有充分的理由,否則應該使用它。
如果您關心速度,則可以嘗試在msvcrt.dll
p /調用memcmp
並以這種方式比較字節數組。 我很難想象會被擊敗。 顯然,您需要先比較長度,如果兩個字節數組的長度相同,則僅調用memcmp
。
p /調用看起來像這樣:
[DllImport("msvcrt.dll", CallingConvention=CallingConvention.Cdecl)]
static extern int memcmp(byte[] lhs, byte[] rhs, UIntPtr count);
但是,只有在真正關心速度的情況下才應該考慮這一點,而純粹的托管替代方法對於您來說太慢了。 因此,請執行一些計時以確保您沒有過早地進行優化。 好吧,甚至可以確保您正在進行優化。
如果轉換為string
速度很快,我會感到非常驚訝。 我希望它會很慢。 實際上,我希望您的代碼會失敗,因為沒有理由讓您的字節數組成為有效的UTF-8。 只是忘記您曾經有過這個想法!
僅當兩個文件匹配uncompress並進行字節比較時, 才比較兩個文件的ZipEntry.Crc
和ZipEntry.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
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.