簡體   English   中英

比較兩個文件哪個更好?

[英]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.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
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM