C # da ikkita faylni solishtirish

Men C #-dagi ikkita faylni solishtirishni istayman va ular boshqalardan farq qiladimi. Ular bir xil fayl nomlariga ega va ular turli xil bo'lsa, ular bir xil bo'ladi. Men bu faylni qo'lda kiritish va o'qishdan hojat qoldirmasdan buni amalga oshirishning tezkor usulini bilishni xohlayman.

Rahmat

14
Lotning bu fikrlari, Toz. O'zingizning ishingiz uchun eng yaxshi ishni qilayotganingizni tekshirish uchun sharhlarni o'qib chiqing. Omad!
qo'shib qo'ydi muallif Random, manba
@Boo: bu belgisi siz 100% to'g'ri.
qo'shib qo'ydi muallif jason, manba
Ilgari foydalanish holatlarini bilish foydali bo'lardi. Qanday qilib .. ETAG HTTP sarlavhasiga qarashingiz mumkin. Veb-server barcha ishlarni qilsin.
qo'shib qo'ydi muallif Sam Axe, manba
G'alati bolalar, ko'plab yaxshi javoblar. Baytni taqqoslash yo'li bilan foydalanib olaman. Vaziyatni batafsilroq tushuntiraman: har 5 daqiqada saytdan fayllarni yuklab qo'yaman va fayl oldingi yuklab olingan faylga ko'ra farq qiladimi? Kuniga bir marta, fayllarni yuklab qo'yishni to'xtatib turadigan vaqt bo'ladi. Menimcha, baytlar bilan taqqoslash byte yaxshiroq bo'lsa, taqqoslashlar ko'pincha bir xil bo'ladi. Yana bir bor rahmat!
qo'shib qo'ydi muallif Toz, manba

7 javoblar

Depending on how far you're looking to take it, you can take a look at Diff.NET

Bu oddiy faylni taqqoslash funksiyasi:

// This method accepts two strings the represent two files to 
// compare. A return value of 0 indicates that the contents of the files
// are the same. A return value of any other value indicates that the 
// files are not the same.
private bool FileCompare(string file1, string file2)
{
     int file1byte;
     int file2byte;
     FileStream fs1;
     FileStream fs2;

    //Determine if the same file was referenced two times.
     if (file1 == file2)
     {
         //Return true to indicate that the files are the same.
          return true;
     }

    //Open the two files.
     fs1 = new FileStream(file1, FileMode.Open, FileAccess.Read);
     fs2 = new FileStream(file2, FileMode.Open, FileAccess.Read);

    //Check the file sizes. If they are not the same, the files 
       //are not the same.
     if (fs1.Length != fs2.Length)
     {
         //Close the file
          fs1.Close();
          fs2.Close();

         //Return false to indicate files are different
          return false;
     }

    //Read and compare a byte from each file until either a
    //non-matching set of bytes is found or until the end of
    //file1 is reached.
     do 
     {
         //Read one byte from each file.
          file1byte = fs1.ReadByte();
          file2byte = fs2.ReadByte();
     }
     while ((file1byte == file2byte) && (file1byte != -1));

    //Close the files.
     fs1.Close();
     fs2.Close();

    //Return the success of the comparison. "file1byte" is 
    //equal to "file2byte" at this point only if the files are 
    //the same.
     return ((file1byte - file2byte) == 0);
}
26
qo'shib qo'ydi
Faqat file1byte == file2byte o'rniga (file1byte - file2byte) == 0 dan foydalanish uchun har qanday sabab bormi?
qo'shib qo'ydi muallif Juan, manba
Bu laxta OS Xda siz va kodini ko'rishni istamaysiz, kodning ko'pligini ko'rsatadigan scrollbar yo'q.
qo'shib qo'ydi muallif Andrei Rînea, manba
Agar fayl faqat bir belgi o'zgartirilsa, bu ishlamay qolishi mumkin. Oqim uzunligi bir xil bo'ladi, lekin kontent bir xil emas. Bu to'g'ri emas!
qo'shib qo'ydi muallif Daniel Peñalba, manba
Kechirasiz, men qo'pol ovoz eshitishni xohlamadim :-) Savol: "Ular bir xil fayl nomlariga ega va ular boshqacha bo'lganda bir xil o'lchov". Shunday qilib, bu yondashish xatoga moyil. Versiya nazorati tizimini ishlab chiqamiz va ushbu turdagi dasturlar SCM bazasida falokatga olib kelishi mumkin.
qo'shib qo'ydi muallif Daniel Peñalba, manba
yordamida dan ko'proq foydalaning!
qo'shib qo'ydi muallif binki, manba
Bu aslida microsoft-ning veb-saytidan olingan. Bu tenglik taqqoslashni, uzunlik taqqoslashni va byte-byte taqqoslashni bajaradi. O'ylaymanki, bu sizning xatoingiz.
qo'shib qo'ydi muallif James Johnson, manba
Kodni to'g'ri deb ayta olaman.
qo'shib qo'ydi muallif Stabledog, manba
Kod to'g'ri, lekin baytni byte taqqoslash bilan bajaradigan bitni ko'rish uchun pastga aylanish kerak. Menimcha, Doniyor pastga aylanmadi.
qo'shib qo'ydi muallif Dave Knight, manba
@Daniel: eski postni qayta tiklash uchun uzr so'rayman, lekin kod bilan qanday muammo borligini tushuntirishga harakat qilyapsizmi? Bu men uchun yaxshi ko'rinadi, u fayl hajmini tekshiradi va bayt tomonidan baytda. Tek belgilar farqi tekshirishdan qanday qilib qochib qutulishi mumkin? Gracias!
qo'shib qo'ydi muallif Evaldas Bieliūnas, manba

Mana shu yerga kirish va faylni o'qimasdan, buni amalga oshirish uchun tezkor usul bormi deb hayron bo'ldim.

Uncha emas.

If the files came with hashes, you could compare the hashes, and if they are different you can conclude the files are different (same hashes, however, does not mean the files are the same and so you will still have to do a byte by byte comparison).

Biroq, fayllardagi barcha baytlardan xeshlar foydalanadi, shuning uchun nima bo'lishidan qat'i nazar, ba'zi holatda byte baytlarini o'qish kerak. Va aslida, byte taqqoslash yo'li bilan faqat byte byte xashni hisoblashdan ko'ra tezroq bo'ladi. Buning sababi, xesh barcha baytlarni bayt-byte bilan solishtirish kabi o'qiydi, ammo xeshlar vaqtni qo'shadigan boshqa hisob-kitoblarni bajaradi. Bundan tashqari, byte-byte taqqoslashni teng bo'lmagan baytning birinchi juftidan o'chirish mumkin.

Va nihoyat, byte-byte o'qish kerak emas. Xeshlar teng bo'lsa, bu fayllar teng degani emas. Bunday holda siz hali ham byte-byte-ni solishtirishingiz kerak.

18
qo'shib qo'ydi
Agar xeshlar bir xil bo'lsa, nega byte uchun baytni solishtirish kerakligini tushuntirib bera olasizmi? Ma'lumotlar boshqacha bo'lsa, nima uchun xeshlar bir xil bo'ladi?
qo'shib qo'ydi muallif scottm, manba
Men bunga kam degandim, bularning barchasini qilayotganimni bilmayman, lekin bu hashingga qo'shilmayman. Xamirlar kelajakda taqqoslash uchun saqlanib qolsa, u joriy foydalanishga ega. Tasvir fayllari bilan buni qildim va tezlik juda ajoyib.
qo'shib qo'ydi muallif Random, manba
@scottm: Teng bo'lmagan fayllar bir xil xeshlarga ega bo'lishi mumkin. Bu qo'g'irchoqbozlik printsipi. Keling, md5dan foydalanamiz. md5 faylning 128-bitli aralashmasini ishlab chiqaradi. Shuning uchun, 2 ^ 128 xil xesh bor. 2 ^ 128 dan ortiq turli fayllar mavjud. Shuning uchun, biz 2 ^ 128 qiymatiga teng bo'lgan bo'shliqqa 2 ^ 128 qiymatdan ortiqroq joy ajratib olganimiz uchun to'qnashuvlar bo'lishi kerak. Xashaklar noyob imzolarni emas.
qo'shib qo'ydi muallif jason, manba
@svick: Ammo bu aniq SHA-1dan foydalanib borish maqsadlaridan biri! Depodaki buzuqliklarni, ehtimol zararli hujumchilar tomonidan aniqlash.
qo'shib qo'ydi muallif jason, manba
@Downvoters: Uch pastga? Qoyil.
qo'shib qo'ydi muallif jason, manba
@svick: Albatta, bu GURUHGA suyanadi, lekin u aralashgan aralashishga moyil. Bu git uchun muammo.
qo'shib qo'ydi muallif jason, manba
@Rastgo'y: Xeshlarni teng bo'lmagan holatga keltirish uchun xeshlarni ishlatishingiz mumkinligini va ularning prekompyuterda foydaliligini bilganingizni esladim. Agar ular oldindan yozilmagan bo'lsa, ular tezroq emas va agar ular teng bo'lsa, biz hali ham bayt-baytga borishimiz kerak.
qo'shib qo'ydi muallif jason, manba
Tepaga: izhor qiling.
qo'shib qo'ydi muallif jason, manba
@Jeyson, bu mumkin muammolar, deb o'ylayman, lekin bu praksistondagi muammo emas. Agar siz xashni buzishga urinayotgan tajovuzkorlarga ega bo'lmasangiz, siz to'qnashuvlar haqida qayg'urmasligingiz kerak.
qo'shib qo'ydi muallif svick, manba
Agar sizda bir xil xassangiz bo'lsa, fayllar bir xil ekanligiga ishonchingiz komil bo'lishi mumkin. To'g'ri aytadigan bo'lsak, siz fayllar baytlarini solishtirishingiz kerak, to'g'ratingiz (va ayniqsa bu sizning xavfsizlikingiz bog'liq bo'lsa). Biroq, git kabi ba'zi tizimlar tizim ichida bir xil xash bilan ikki xil fayl ko'rinmaydi haqiqatga tayanadi. Albatta, bularning barchasi yaxshi xashni nazarda tutadi, bu narsa GetHashCode() kabi emas.
qo'shib qo'ydi muallif svick, manba

Xo'sh, faylda vaqt belgilarini yozib olishingiz mumkinligiga ishonchim komil emas. Aks holda, sizning yagona muqobilingiz fayllarning mazmunini taqqoslash.

Oddiy yondashuv fayllarni byte-byte bilan taqqoslashdir, lekin faylni boshqalar bilan taqqoslashni rejalashtirmoqchi bo'lsangiz, fayllarning hashcode-ni hisoblashingiz va uni taqqoslashingiz mumkin.

Quyidagi kod zarrachalari buni qanday qilish mumkinligini ko'rsatadi:

    public static string CalcHashCode(string filename)
    {
        FileStream stream = new FileStream(
            filename,
            System.IO.FileMode.Open,
            System.IO.FileAccess.Read,
            System.IO.FileShare.ReadWrite);

        try
        {
            return CalcHashCode(stream);
        }
        finally
        {
            stream.Close();
        }
    }

    public static string CalcHashCode(FileStream file)
    {
        MD5CryptoServiceProvider md5Provider = new MD5CryptoServiceProvider();
        Byte[] hash = md5Provider.ComputeHash(file);
        return Convert.ToBase64String(hash);
    }

Faylni boshqalar bilan taqqoslashni rejalashtirmoqchi bo'lsangiz, faylni aralashtirishni saqlashingiz va uni taqqoslashingiz mumkin. Bir taqqoslash uchun bayt-to-bayt taqqoslash yaxshi. Siz faylni o'zgartirganda aralashmalarni qayta yozishingiz kerak, lekin agar siz katta taqqoslashni (bir martadan ortiq) amalga oshirsangiz, men sizni aralashgan usuldan foydalanishni maslahat beraman.

4
qo'shib qo'ydi
Biz xashning mukammal xash yoki yo'qligi haqida gapirganda o'xshaydi. MD5 hashing algoritmi emas, balki mukammaldir, shuning uchun Jeyson to'g'ri - hash to'qnashuvi ehtimoli mavjud.
qo'shib qo'ydi muallif Ben, manba
@Jeyson: Bu faqatgina ijodiy suhbatlar. Bizning vaziyatimizda disk daraxtini uzoq disk daraxtiga solishtiramiz. Ikkala diskda ham, uzoqdan ham oldindan hisoblangan xeshlar bor, shuning uchun muammo faqat faylga bir juft xashni taqqoslaydi. Shuningdek, biz faylni o'zgartirganda xashni qayta hisoblaymiz. Shubhasiz, buni qilishning eng yaxshi usuli.
qo'shib qo'ydi muallif Daniel Peñalba, manba
@Jason: Fikr har qanday joyga saqlanadi va bu haqda foyda oladi. Albatta, agar siz faqat bir marta hisoblasangiz, byte-byte taqqoslashni bajaring.
qo'shib qo'ydi muallif Daniel Peñalba, manba
@Daniel Peñalba: Ammo xeshlar fayllar bir xil bo'lsa, 100% aniq bo'lganda bayt-baytga borishingiz kerak.
qo'shib qo'ydi muallif jason, manba
@svick: Ha. Bayt-byte erta tugatilishi mumkin, xamirlar allaqanday byte-byte-xam kabi barcha tarkibni o'qiydi va agar xeshlar teng bo'lsa, baribir byte-byte-ga o'tishimiz kerak.
qo'shib qo'ydi muallif jason, manba
Yo'q! Siz hashoratlar teng bo'lsa, siz STILL baytlarini bayt bilan solishtirishingiz kerak. Agar xeshlar teng bo'lmasa, bayt-baytni tezroq bajarish tezroq bo'ladi, chunki u birinchi teng bo'lmagan juft baytda to'xtatishi mumkin, biroq hash fayl orqali butun yo'lni bosishi kerak! Argh!
qo'shib qo'ydi muallif jason, manba
Yozuv uchun ikkala alohida fayl ham bir xil fayl nomi va uzunligi bilan deyarli ikki xil vaqt belgiga ega bo'lishi kerak. Boshqa hech narsa bo'lmasa, ikkinchi nusxasini yozish uchun kamida bir necha milisaniyani oladi.
qo'shib qo'ydi muallif AllenG, manba
Agar har ikkala fayl mavjud bo'lsa, men har ikkala uchun aralashmalarni hisoblash to'g'ridan-to'g'ri taqqoslagandan ko'ra aslida sekinroq bo'ladi deb o'ylayman.
qo'shib qo'ydi muallif svick, manba

Agar fayl nomlari bir xil bo'lsa va fayl hajmi bir xil bo'lsa, demak, ular mazmunni o'rganmasdan turli kontentlarga ega yoki yo'qligini bilishning hech qanday usuli yo'q.

3
qo'shib qo'ydi
Bu javob, hozirgi paytda, bu masalada faqatgina boshqa to'g'ri javob (hozirgi). U pastga tushmasligi kerak.
qo'shib qo'ydi muallif jason, manba
Men Jeyson bilan bo'ldim: past ovoz berganingizda sharh bering.
qo'shib qo'ydi muallif AllenG, manba

har bir fayl oqimini MD5 hasher orqali o'tkazib, xeshlarni solishtiring.

2
qo'shib qo'ydi
@Jason, agar fayllar bir xil bo'lmasa, muammo ham bor. Savolga ko'ra, fayllar bor, lekin ular bo'lmasligi mumkin, deb hisoblaymiz. Hisoblangan xeshlar teng darajada bo'ladi.
qo'shib qo'ydi muallif Random, manba
@Boo: Astounding. OP, fayllar bir xil yoki yo'qligini bilishni istaydi, agar ular bir xil bo'lsa.
qo'shib qo'ydi muallif jason, manba
@ L. B: Ikki faylni farqlash uchun solishtirish kriptografik dastur emas. Biz ikkita fayl ehtimol teng yoki yo'qligini tekshirishga harakat qilmaymiz, aksincha ular teng bo'lsa.
qo'shib qo'ydi muallif jason, manba
@Rastad: Siz aytayotganingizni tushunmayapman.
qo'shib qo'ydi muallif jason, manba
@ L.B: Xuddi shu muammo har qanday xashlash algoritmiga taalluqlidir. QAChON. Xushbo'y joylar katta bo'shliqni egallaydi va uni kichik joyga tashlaydi. Har hashing algoritmini to'qnashuvlar va ularning ko'plari bo'ladi.
qo'shib qo'ydi muallif jason, manba
Hex kodlari d131dd02c5e6eec4693d9a0698aff95c 2fcab58712467eab4004583eb8fb7f89 55ad340609f4b30283e488832571415a 085125e8f7cdc99fd91dbdf280373c5b d8823e3156348f5bae6dacd436c919c6 dd53e2b487da03fd02396306d248cda0 e99f33420f577ee8ce54b67080a80d1e c69821bcb6a8839396f9652b6ff72a70 va d131dd02c5e6eec4693d9a0698aff95c 2fcab50712467eab4004583eb8fb7f89 55ad340609f4b30283e4888325f1415a 085125e8f7cdc99fd91dbd7280373c5b d8823e3156348f5bae6dacd436c919c6 dd53e23487da03fd02396306d248cda0 e99f33420f577ee8ce54b67080280d1e c69821bcb6a8839396f965ab6ff72a70 Shu md5 hash bor. Ular teng emas.
qo'shib qo'ydi muallif jason, manba
Yo'q, demak, ular bir xil xash bor. Bu "fayllar bir xil" degan ma'noni anglatmaydi. "
qo'shib qo'ydi muallif jason, manba
Siz e'tibor bermayapsiz: siz hashoratlar teng bo`lsa STILL baytlarini taqqoslashingiz kerak. Xatchlarni ishlatish kam ish emas, chunki u qo'shimcha ishidir, chunki siz byte-byte taqqoslashni va kodni xashing algoritmini ishlatishingiz kerak va mantiqiylik esa byte-byte ishlatiladi. xeshlar teng.
qo'shib qo'ydi muallif jason, manba
Lekin agar xeshlar teng bo'lsa, siz hali ham fayllarni qo'lda o'qishingiz va byte byte bilan solishtirishingiz kerak, ular aslida tengdirlar. Bu kam ish emas. Baytlarni taqqoslash yo'li bilan baytga ehtiyoj sezmaysiz.
qo'shib qo'ydi muallif jason, manba
Bu faqat byte bayt bilan taqqoslagandan ko'ra tez emas va siz xeshlar teng bo'lganda bayt tomonidan baytga o'tishingiz kerak!
qo'shib qo'ydi muallif jason, manba
MD5dan kim foydalanadi?
qo'shib qo'ydi muallif L.B, manba
@Jeyson, bilaman, siz nazariy jihatdan haqlisiz, lekin kriptografik ilovalarning aksariyati zamonaviy xash algs.s. Fayl taqqoslash uchun ham xuddi shunday qilardim
qo'shib qo'ydi muallif L.B, manba
Ushbu suhbat tugadi.
qo'shib qo'ydi muallif Sam Axe, manba
Kichik dasturiy ish. Protsessorlar (hozircha), har qanday ortiqcha ishni bajarish kerak bo'lsa, g'amxo'rlik qiladi. Zamonaviy CPUlar qisqa vaqt ichida juda ko'p ish qilmaguningizcha qo'shimcha ishni sezmaysiz. Ammo OP bu holni ko'rsatmadi.
qo'shib qo'ydi muallif Sam Axe, manba
@Jeyson: "statistik ehtimolliklar ichida" ning qaysi qismi chalkashlik kasb etadi? Albatta, to'qnashuvlar bor. Haqiqiy dunyodagi to'qnashuvning xushbo'yligi yo'qolib boraveradi. Bu laboratoriya emas.
qo'shib qo'ydi muallif Sam Axe, manba
Yo'q. Agar xeshlar teng bo'lsa, qo'l bilan byte-byte taqqoslashni amalga oshirishga hech qanday sabab yo'q. Teng xaftalar (statistik ehtimolliklar ichida) fayllar bir xilligini anglatadi.
qo'shib qo'ydi muallif Sam Axe, manba
Uning kam ishi. Va OP o'zlarini bartaraf qilishdan qochish istagini kuchaytirdi.
qo'shib qo'ydi muallif Sam Axe, manba

Ularga mos bo'lmagan fayllar bo'lsa, unda KDiff yoki WinMerge kabi turli xil vositalardan foydalaning. Bu ular turli xilligini ta'kidlaydi.

http://kdiff3.sourceforge.net/

http://winmerge.org/

2
qo'shib qo'ydi
Savol: .net-da ikkita faylni dasturiy jihatdan taqqoslash haqida. Asker kodni C #-da yozadi va u ikki faylni solishtirish uchun yozayotgan dasturga muhtoj. Ehtimol, shellout yoki GUI vositasiga qiziqish yo'q.
qo'shib qo'ydi muallif binki, manba

Faylni oqimga o'qing, so'ngra oqimni kesib tashlang. Bu sizga taqqoslash uchun ishonchli natija berishi kerak.

byte[] fileHash1, fileHash2;

using (SHA256Managed sha = new SHA256Managed())
{
    fileHash1 = sha.ComputeHash(streamforfile1);
    fileHash2 = sha.ComputeHash(streamforfile2);
}

for (int i = 0; (i < fileHash1.Length) && (i < fileHash2.Length); i++)
    {
        if (fileHash[i] != fileHash2[i]) 
        { 
             //files are not the same
             break; 
        }
    }
0
qo'shib qo'ydi