2010-01-29 33 views
7

Cách cách dễ nhất để tìm hiểu xem hai tệp văn bản khác nhau theo chương trình là gì? Cho hai tập tin tôi chỉ cần biết liệu chúng có khác nhau hay không. Đây là một công cụ nhanh chóng để giúp đỡ với một hợp nhất đặc biệt khó chịu (chuyển ngôn ngữ từ VB sang C# trong một chi nhánh (yay!) Và thực hiện nhiều thay đổi trong khác), nó sẽ không đi vào sản xuất.Cách dễ nhất để tìm hiểu xem hai tệp có khác nhau theo chương trình không?

giải pháp có thể:

  1. Hash cả các file và so sánh băm
  2. Kéo các tập tin trong và chỉ cần làm một chuỗi so sánh
  3. Gọi ra một công cụ diff bên ngoài (không may WinMerge không có một CLI cho điều này)

Nếu có thể bỏ qua không gian trắng sẽ tuyệt vời nhưng tôi không quan tâm nhiều đến nó. Điều chính là nó cần phải nhanh chóng và dễ dàng.

Tôi đang sử dụng .Net 3.5sp1 bằng cách này. Cảm ơn bất kỳ ý tưởng hoặc con trỏ.

+0

http://unxutils.sourceforge.net/ có gnu khác biệt cho cửa sổ. 'diff -q file1 file2' là cú pháp bạn muốn – KitsuneYMG

+0

FWIW, một công cụ tìm khác biệt ba chiều sẽ giúp hiển thị sự khác biệt giữa hai tệp VB trong khi so sánh chúng với tệp C# mới. Ngoài So sánh 3 PRO (BC3 PRO) và Araxis Merge cả hai đều có so sánh 3 chiều và hợp nhất. BC3 Pro chỉ là 50 đô la và là một trong những công cụ lập trình tốt nhất mà bạn từng sử dụng để xử lý các hợp nhất và các khác biệt tương tác. – Adisak

Trả lời

11

Có một bài viết trong Cơ sở Kiến thức Microsoft, hy vọng nó sẽ giúp ích. Họ so sánh các byte để xem liệu hai tập tin khác nhau - How to create a File-Compare function in Visual C#

+0

Liên kết KB đó đã chết, tôi tìm thấy một tệp lưu trữ tại đây: http://www.java2s.com/Code/CSharp/File-Stream/Comparesthecontentof2files.htm –

10

Cách nhanh nhất để làm điều đó là so sánh byte-to-byte của các tệp được tải trên luồng. Hashing cả hai tập tin sẽ mất quá nhiều thời gian cho các tập tin lớn, chuỗi so sánh quá, các công cụ bên ngoài quá.

So sánh từng byte sẽ là tốt nhất cho bạn, vì nó sẽ chỉ đạt đến EOF của tệp khi cả hai đều giống hệt nhau.

Nếu bạn so sánh băm, so sánh chuỗi hoặc công cụ bên ngoài, bạn sẽ phải trải qua toàn bộ tệp tất cả các lần bạn so sánh, so sánh từng byte sẽ chỉ thực hiện trong trường hợp chúng giống nhau.

+1

+1: đơn giản, hiệu quả, chính xác 100% và rõ ràng là nhanh nhất – chburd

+3

Về mặt kỹ thuật không phải nhanh nhất. Nhanh nhất liên quan đến việc kiểm tra kích thước tập tin đầu tiên cho từ chối tầm thường. Ngoài ra, số lượng thời gian để tính toán một băm đơn giản có thể được tối thiểu so với thời gian IO - đầu tiên chắc chắn rằng bạn đang thực hiện bộ nhớ đệm tập tin với kích thước tập tin phong nha đọc. Ngoài ra, so sánh băm không có phân tích cú pháp toàn bộ tệp để từ chối - bạn có thể chia nhỏ dữ liệu và chỉ so sánh các khối băm. Chunked hash cmp bằng cách sử dụng bộ nhớ cache tìm nạp trước bộ nhớ có thể nhanh hơn 2-3 lần so với so sánh byte ngây thơ (nhưng nó có khả năng sẽ không nhanh bằng cách sử dụng tính năng tìm nạp trước của SIMD/SIAR). Thêm vào đó bạn có thể dễ dàng đa băm hoặc cmp. – Adisak

3

Có sử dụng thuật toán băm MD5 để so sánh kết quả không? Đây là số example.

+0

+1 Tôi đã triển khai giải pháp này. Hoạt động tốt mọi lúc. –

+1

vâng, kết quả tuyệt vời, hiệu suất kém, hãy thử so sánh 2 tệp với 100MB mỗi lần, sẽ mất một thời gian dài, không quan trọng các tệp khác nhau như thế nào, làm byte-by-byte sẽ dừng toàn bộ quá trình trong lần đầu tiên khác nhau byte nó tìm thấy. – Tufo

+0

+1 @Tufo - điểm tốt. –

0

Từ câu hỏi - dễ nhất & bản tập tin

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

Nó không phải là nhanh hay đẹp, nhưng thật dễ dàng

4

Kiểm tra theo byte, đây là một số mã:

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

Tôi khuyên bạn nên trang trí FileStream bằng luồng đệm hoặc đọc luồng theo khối. –

+0

Tôi có vẻ như FileStream đã được đệm, http://blogs.msdn.com/b/brada/archive/2004/04/15/114329.aspx, vì vậy tôi không nghĩ rằng bất kỳ gói nào sẽ giúp ích. – derkyjadex

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

Tất nhiên điều này thay đổi giữa VB và C#

1

Nó cũng phụ thuộc vào những gì bạn đang cố giải quyết. Bạn đang cố gắng trả lời câu hỏi: trong thư mục N tệp này, tìm tất cả các bản sao chính xác? Hay hai tệp này giống hệt nhau?

Nếu bạn đặc biệt chỉ so sánh hai tệp, thì việc sử dụng kiểm tra byte bằng byte sẽ hiệu quả hơn. Nhưng nếu bạn đang cố gắng tìm tất cả các cặp trùng lặp trong N tệp, thì băm MD5 tốt hơn, vì bạn có thể tạo và lưu trữ giá trị băm MD5 một lần và so sánh giá trị nhỏ hơn nhiều này cho mỗi cặp tệp.Khác khôn ngoan bạn sẽ được iterating qua từng tập tin byte dòng cho mỗi tập tin khác trong thư mục.

1

Tôi đã triển khai phiên bản khác biệt rất chuyên biệt một năm trước (tôi đã có tệp với hơn 6 GB và phải so sánh sau đó). Vì vậy, tôi biết các hoạt động nội bộ của diff (rất nhiều của bản sao & dán, tất nhiên). Một số suy nghĩ:

  • Nếu bạn muốn đơn giản biết nếu chúng khác nhau, hãy so sánh chúng theo byte. Tối ưu hóa bằng cách kiểm tra xem kích thước của chúng (độ dài) có khác nhau không và sau đó đọc từng tệp một byte và kiểm tra xem chúng có khác nhau hay không. Bạn không cần phải quan tâm đến việc đệm, vì API tệp của bạn nên làm điều đó cho bạn (.Net hiện).
  • Nếu có một số nguyên tắc mà bạn muốn áp dụng cho các so sánh:
    • Nếu bạn sẽ bỏ qua khoảng trắng hoặc bất kỳ ký tự khác, khi bạn đọc các byte, kiểm tra xem nó nên bỏ qua. Nếu cần, đọc tiếp theo, nhưng chỉ trên tập tin đó.
    • Nếu có các quy tắc sẽ được áp dụng dòng khôn ngoan, sau đó đọc từng dòng tệp. Sau đó, băm dòng, bỏ qua bất cứ điều gì bạn muốn bỏ qua.
    • Hãy nhớ rằng dòng có thể được xác định là bản ghi có độ dài biến đổi với dòng mới làm dấu kết thúc (dấu tách). Vì vậy, bạn có thể xác định dòng là bất cứ điều gì bạn muốn và đọc chính xác điều đó, băm và so sánh.

Tôi có thể đóng góp mã nếu bạn muốn. Các tệp diff'ing phức tạp hơn, bởi vì bạn cũng sẽ xuất ra những gì khác nhau.

Các vấn đề liên quan