2010-01-29 11 views
7

Qual è il modo più semplice per scoprire se due file di testo sono diversi a livello di codice? Dati due file, ho solo bisogno di sapere se sono diversi o meno. Questo è uno strumento rapido per aiutare con una unione particolarmente sgradevole (passare da VB a C# in un ramo (yay!) E fare molti cambiamenti nell'altro), non andrà in produzione.Qual è il modo più semplice per scoprire se due file sono diversi a livello di codice?

Possibili soluzioni:

  1. Hash entrambi i file e confrontare l'hash
  2. scaricare i file e fare solo una stringa confrontare
  3. chiamare a uno strumento esterno diff (purtroppo WinMerge non ha una CLI per questo)

Se possibile ignorare lo spazio bianco sarebbe fantastico ma non mi interessa molto. La cosa principale è che deve essere semplice e veloce.

Sto usando .Net 3.5sp1 a proposito. Grazie per qualsiasi idea o suggerimento.

+0

http://unxutils.sourceforge.net/ ha gnu diff per windows. 'diff -q file1 file2' è la sintassi che si desidera – KitsuneYMG

+0

FWIW, uno strumento diff a tre vie aiuta a mostrare le differenze tra i due file VB mentre li confronta con il nuovo file C#. Oltre a Confronta 3 PRO (BC3 PRO) e Araxis Merge hanno entrambi un confronto e fusione a 3 vie. BC3 Pro ha solo $ 50 ed è uno dei migliori strumenti di programmazione che tu possa mai utilizzare per gestire le fusioni e le differenze interattive. – Adisak

risposta

11

C'è un articolo nella Microsoft Knowledge Base, spero che sia d'aiuto. Si confrontano i byte per vedere se due file sono diversi - How to create a File-Compare function in Visual C#

+0

Che il collegamento KB sia morto, ho trovato un archivio qui: http://www.java2s.com/Code/CSharp/File-Stream/Comparesthecontentof2files.htm –

10

Il modo più veloce per farlo è confrontare byte per byte dei file caricati su un flusso. L'hashing di entrambi i file richiederà troppo tempo per i file di grandi dimensioni, anche per il confronto delle stringhe, anche per gli strumenti esterni.

Il confronto tra byte e byte sarà il migliore per voi, poiché raggiungerà l'EOF dei file solo quando entrambi sono identici.

Se si esegue il confronto di hash, confronto di stringhe o strumenti esterni, è necessario passare attraverso l'intero file tutte le volte che si confronta, confrontando byte a byte lo si farà solo nel caso in cui siano identici.

+1

+1: semplice, efficiente, corretto al 100% e chiaramente il più veloce – chburd

+3

Tecnicamente non il più veloce. Il più veloce comporta il controllo delle dimensioni dei file prima per il rigetto banale. Inoltre, la quantità di tempo per calcolare un semplice hash può essere minima rispetto al tempo di I/O - per prima cosa assicurati di eseguire il caching dei file con file di dimensioni decenti. Inoltre, hash compare non ha analizzato l'intero file da rifiutare: puoi tagliare i dati e confrontare solo i blocchi hash. L'hash Chunked di cmp che utilizza il precaricamento della cache del processore può essere 2-3 volte più veloce rispetto a un confronto di byte ingenuo (ma probabilmente non sarà veloce come un cmp SIMP/SIAR con prefetching). Inoltre puoi facilmente annullare l'hash o il cmp multithread. – Adisak

3

Utilizzare un algoritmo MDash hash per confrontare i risultati? Ecco uno example.

+0

+1 Ho implementato questa soluzione. Funziona alla grande ogni volta. –

+1

sì, grandi risultati, prestazioni pessime, prova a confrontare 2 file con 100 MB ciascuno, ci vorrà molto tempo, non importa quanto siano diversi i file, facendo byte per byte si fermerà l'intero processo nel primo diverso byte che trova. – Tufo

+0

+1 @Tufo - buon punto. –

0

Dalla domanda - più semplice & Text file di

StreamReader sr1 = new StreamReader(filePath1); 
StreamReader sr2 = new StreamReader(filePath2); 
if (sr1.ReadToEnd() == sr2.ReadToEnd()) 
{ do stuff } 

Non è veloce o abbastanza, ma è facile

4

Controllare byte per byte, ecco qualche codice:

public static bool AreFilesIdentical(string path1, string path2) 
{ 
    using (FileStream file1 = new FileStream(path1)) { 
     using (FileStream file2 = new FileStream(path2)) { 

      if (file1.Length == file2.Length) { 
       while (file1.Position < file1.Length) { 
        if (file1.ReadByte() != file2.ReadByte()) { 
         return false; 
        } 
       } 
       return true; 
      } 
      return false; 
     } 
    } 

} 
+0

Suggerirei di decorare FileStream con un flusso bufferizzato o di leggere lo stream per blocchi. –

+0

Sembrerebbe che FileStream sia già stato memorizzato nel buffer, http://blogs.msdn.com/b/brada/archive/2004/04/15/114329.aspx, quindi non credo che nessun involucro sarebbe d'aiuto. – derkyjadex

0
if ($file1 != $file2) return true; 

Ovviamente questo varia tra VB e C#

1

Dipende anche da ciò che si sta tentando di risolvere. Stai cercando di rispondere alla domanda: in questa directory di file N trovi tutti i duplicati esatti? O questi due file sono esattamente uguali?

Se si stanno confrontando in modo specifico due file, l'utilizzo di un controllo byte per byte è più efficiente.

Ma se si sta cercando di trovare tutte le coppie duplicate in N file, allora un hash MD5 è migliore, perché è possibile creare e memorizzare il valore hash MD5 una volta e confrontare questo valore molto più piccolo per ogni coppia di file.Altrimenti starete ripetendo su ogni flusso di byte di file per ogni altro file nella directory.

1

Ho implementato una versione molto specializzata di diff un anno fa (avevo file con oltre 6 GB e dovevo confrontare quindi). Quindi conosco il funzionamento interno di diff (lotto di copia & incolla, ovviamente). Alcuni pensieri:

  • Se si desidera sapere se sono diversi, confrontarli byte per byte. Ottimizza controllando se le loro dimensioni (lunghezze) sono diverse e quindi leggi i file un byte alla volta e controlla se sono diversi. Non devi preoccuparti del buffering, dal momento che l'API del tuo file dovrebbe farlo per te (.Net lo fa).
  • Se ci sono alcune regole che desideri applicare al confronto tra:
    • Se si ignora gli spazi bianchi o di qualsiasi altro carattere, come si legge il byte, controlla se esso dovrebbe essere ignorato. Se è il caso, leggi quello successivo, ma solo su quel file.
    • Se ci sono regole che verranno applicate in linea, quindi leggere il file riga per riga. Quindi elimina la linea, ignorando qualsiasi cosa tu voglia ignorare.
    • Ricordare che la riga può essere definita come un record di lunghezza variabile con una nuova riga come terminatore (separatore). In questo modo puoi definire la linea come vuoi e leggerla esattamente, cancellarla e confrontarla.

posso contribuire con il codice se si desidera. La diffusione di file è più complessa, poiché si genererà anche ciò che è diverso.

Problemi correlati