Có nhất thiết phải đọc từng byte đơn để kiểm tra xem một tệp được sao chép có giống với bản gốc không?


16

Gần đây tôi đã biết về một chương trình gọi là Total Commander. Đây là một sự thay thế Windows Explorer và có nội dung riêng để sao chép các tệp. Để kiểm tra xem các tệp có giống nhau hay không, thay vì tính CRC, nó sẽ kiểm tra từng byte một, theo từng nghĩa một, trên cả bản gốc và bản sao.

Câu hỏi của tôi là: Điều này có cần thiết không? CRC hoặc bất kỳ kỹ thuật như vậy có thể đi sai? Bạn có nên, như một lập trình viên, thử và thực hiện hệ thống hoàn hảo nhưng chậm chạp này, hay nó quá cực đoan?


3
Hãy xem cách "rsync" xử lý việc này.

21
Tính toán CRC (hoặc, tốt hơn, sha1sums) trên cả hai tệp yêu cầu đọc từng byte. Nếu bạn thực hiện so sánh theo từng byte, bạn có thể thoát ngay khi thấy không khớp - và bạn không phải lo lắng về hai tệp khác nhau có cùng một tổng kiểm tra (mặc dù điều đó không chắc chắn cho sha1sum) . Mặt khác, so sánh tổng kiểm tra rất hữu ích khi bạn so sánh các tệp không nằm trên cùng một máy; tổng kiểm tra có thể được tính cục bộ và bạn không phải chuyển toàn bộ nội dung qua mạng.
Keith Thompson

3
Đối với khả năng va chạm, nếu bạn sử dụng một hash đàng hoàng như sha1sumbạn khá nhiều không cần phải lo lắng về nó, trừ khi ai đó là cố ý và tốn kém xây dựng các file mà sha1sums va chạm. Tôi không có nguồn cho việc này, nhưng tôi đã nghe (trong ngữ cảnh của git) rằng xác suất hai tệp khác nhau có cùng sha1sum giống như xác suất của mọi thành viên trong nhóm phát triển của bạn bị ăn thịt sói. Cùng ngày. Trong các sự cố hoàn toàn không liên quan.
Keith Thompson

5
@KeithThndry: Tôi nghĩ rằng nhận xét đầu tiên của bạn phải là một câu trả lời :-)
Dean Harding

6
Câu trả lời ngắn gọn - Không, tốt nhất là để máy tính của bạn làm điều đó cho bạn.
psr

Câu trả lời:


40

Tính toán CRC (hoặc, tốt hơn, sha1sums) trên cả hai tệp yêu cầu đọc từng byte. Nếu bạn thực hiện so sánh theo từng byte, bạn có thể thoát ngay khi thấy không khớp - và bạn không phải lo lắng về hai tệp khác nhau có cùng một tổng kiểm tra (mặc dù điều đó không chắc chắn cho sha1sum) . Vì vậy, nếu bạn đang thực hiện so sánh cục bộ, so sánh theo byte sẽ ít nhất nhanh bằng so sánh tổng kiểm tra (trừ khi bạn đã tính toán tổng kiểm tra bằng mọi cách).

Mặt khác, so sánh tổng kiểm tra rất hữu ích khi bạn so sánh các tệp không nằm trên cùng một máy; tổng kiểm tra có thể được tính cục bộ và bạn không phải chuyển toàn bộ nội dung qua mạng.

Phương pháp lai cũng có thể. Ví dụ: bạn có thể tính toán và so sánh tổng kiểm tra cho hai tệp một đoạn, điều này có thể tránh đọc toàn bộ tệp ( nếu chúng khác nhau) trong khi cũng tránh truyền toàn bộ tệp qua mạng. Các giao thức rsync làm điều gì đó như thế này.

Lưu ý rằng việc sử dụng CRC đơn giản mang lại cho bạn cơ hội va chạm công bằng, như Dave Rager đã đề cập trong câu trả lời của mình. Sử dụng ít nhất sha1sum, hoặc thậm chí một cái gì đó gần đây hơn. (Đừng cố phát minh thuật toán băm của riêng bạn; những người đã phát triển sha1sum biết nhiều về công cụ này hơn cả chúng ta.)

Đối với khả năng va chạm, nếu bạn sử dụng một hash đàng hoàng như sha1sum bạn khá nhiều không cần phải lo lắng về nó, trừ khi ai đó là cố ý và tốn kém xây dựng các file mà sha1sums va chạm (tạo ra va chạm như vậy là không khả thi khi tôi lần đầu tiên viết này , nhưng tiến độ đang được thực hiện ). Trích dẫn "Pro Git" của Scott Chacon , phần 6.1 :

Đây là một ví dụ để cung cấp cho bạn ý tưởng về những gì sẽ cần để có được một vụ va chạm SHA-1. Nếu tất cả 6,5 tỷ người trên Trái đất đang lập trình và cứ sau mỗi giây, mỗi người sẽ tạo ra mã tương đương với toàn bộ lịch sử hạt nhân Linux (1 triệu đối tượng Git) và đẩy nó vào một kho lưu trữ Git khổng lồ, phải mất 5 năm cho đến khi kho lưu trữ đó chứa đủ các đối tượng để có xác suất 50% cho một vụ va chạm đối tượng SHA-1. Xác suất cao hơn tồn tại là mọi thành viên trong nhóm lập trình của bạn sẽ bị sói tấn công và giết chết trong các sự cố không liên quan trong cùng một đêm.

Tóm lược :

So sánh byte theo byte là tốt cho so sánh cục bộ. sha1sum là tốt để so sánh từ xa, và không có cơ hội dương tính giả.


Cần lưu ý rằng định nghĩa chung của hàm băm "tốt" bao gồm thuộc tính rằng rất khó để tạo các đầu vào khác nhau với cùng một hàm băm ("chống va chạm"). SHA-1 có một số điểm yếu (về mặt lý thuyết) về mặt này, nhưng bạn không thể chỉ "xây dựng hai tệp va chạm", ngay cả khi bạn cố gắng khá nhiều.
sleske

@sleske: Đã cập nhật
Keith Thompson

1
@KeithThndry Tôi đang nâng cao câu trả lời, nhưng tôi nghĩ đã đến lúc cập nhật trên SHA1 - The SHAppening
K.Steff

Tôi nghi ngờ họ sẽ cáu kỉnh nếu bạn cố gắng lưu trữ repo lý thuyết này trên GitHub.
hBy2Py

1
Tôi có nghĩa là họ sẽ không vui khi có nhiều exabyte mỗi giây của lực đẩy dữ liệu đối với họ. :-)
hBy2Py

10

Đây là một cách khác để suy nghĩ về nó.

Nếu không có khả năng hai tệp khác nhau có cùng CRC, thì bằng cách mở rộng, điều đó có nghĩa là mọi tệp có thể được biểu thị bằng CRC duy nhất. Nếu CRC nhỏ hơn tệp gốc thì nó sẽ biểu thị dạng nén không mất dữ liệu. Nếu không, bạn cũng sẽ làm tốt việc so sánh các tệp gốc vì bạn sẽ so sánh cùng số byte.

Về lý thuyết, bạn có thể sử dụng nén không mất dữ liệu của cả hai mặt so sánh để giảm số byte cần thiết trong so sánh, nhưng đó là một việc vặt vì bạn lãng phí nhiều chu kỳ hơn và phải đọc từng byte của cả hai tệp để thực hiện nén . Đó là, để mã hóa từng byte (và theo thứ tự) trong sơ đồ nén không mất dữ liệu, trước tiên bạn phải đọc nó và cắm nó vào thuật toán, phải không? Trò chơi kết thúc.

Đây là một sự tương tự:
Nếu bạn muốn một cách nhanh chóng xác định xem hai tài liệu được in có giống nhau mà không so sánh từng chữ cái hay không, bạn có thể so sánh số lượng chữ cái trên mỗi dòng của tài liệu. Nếu tất cả các số trùng khớp, tỷ lệ cược cải thiện đáng kể rằng các tài liệu giống hệt nhau, tuy nhiên không ai có thể tranh luận rằng bạn có thể chắc chắn rằng mọi chữ cái đều giống nhau khi sử dụng phương pháp này.


3

Cách hoàn hảo duy nhất để kiểm tra các tệp giống nhau là byte để so sánh byte. Một cách khác để có được xấp xỉ hợp lý là tính toán một hàm băm như MD5 cho các tệp và so sánh chúng. Có thể có một vụ va chạm băm nhưng không có khả năng lắm.

Tôi sẽ tưởng tượng byte để so sánh byte sẽ nhanh hơn so với tính toán hàm băm trên cả hai tệp tại thời điểm bạn đang thực hiện so sánh. Tuy nhiên, nếu ứng dụng của bạn tính toán trước hàm băm và lưu trữ dữ liệu meta về các tệp của bạn, việc so sánh giá trị băm sẽ nhanh hơn đáng kể.

CRC có lẽ không phải là hướng đi vì nó chỉ là một cơ chế phát hiện lỗi, không phải là hàm băm. (hoặc băm kém với nhiều va chạm có thể xảy ra)


Đồng ý +1. Rất có khả năng ổ cứng của bạn bị hỏng so với sự cố ngẫu nhiên của chức năng băm tốt (CRC32 yếu - cũng đồng ý).
Michał Šrajer

2

Để chắc chắn 100% hai tệp giống hệt nhau, bạn thực sự cần phải kiểm tra các byte.

Tại sao? Va chạm băm, đó là lý do tại sao! Tùy thuộc vào thuật toán được sử dụng để băm, va chạm có thể ít nhiều có thể xảy ra, nhưng có thể là không ít hơn. Thực hiện theo các bước sau:

  1. Kiểm tra kích thước tập tin
  2. Kiểm tra các loại mime
  3. Kiểm tra băm
  4. Kiểm tra một vài giá trị ngẫu nhiên và so sánh các bit

Sẽ cung cấp cho bạn một sự đảm bảo rất cao về sự chắc chắn rằng hai tệp giống nhau, tuy nhiên có một cơ hội rất nhỏ (cực kỳ) mà bạn có va chạm trên tay. Sự lựa chọn của bạn muốn đi bao xa với so sánh của bạn sẽ được quyết định bởi tình huống.


Tôi nghĩ rằng nếu bạn chọn một thuật toán băm tốt, 2. và 4. sẽ không cung cấp cho bạn bất kỳ chất lượng "bằng" thực sự tăng nào. Có lẽ 1. chỉ cần thiết cho băm yếu.
Michał Šrajer

1
-1 Điều này không có ý nghĩa. Nếu bạn chọn một thuật toán băm tốt, tất cả các bước khác là không cần thiết. 1. và 4. thực sự đã được bao phủ bởi những gì băm làm và 2. là vô nghĩa (Hầu hết các hệ thống tệp thậm chí không có khái niệm "loại MIME" và ngay cả khi chúng có, nó sẽ thêm rất ít thông tin).
sleske

@sleske Tôi đang nói thay vì bẻ khóa tập tin, đây là một hoạt động chuyên sâu, bạn có thể thực hiện một số thao tác sơ bộ không quá nặng.

Tôi chỉ tái tạo 1 và 3 rất nhiều ý nghĩa. (1) sẽ gắn cờ hầu hết các trường hợp của các tệp khác nhau để tiết kiệm nhu cầu tính toán hàm băm. Cuộc đụng độ băm trên cùng một tệp có độ dài rất khó xảy ra nên không đáng lo ngại.
Michael Shaw

1

Như những người khác đã nói rằng việc so sánh từng byte một sẽ nhanh hơn nếu hai tệp nằm trên cùng một hệ thống. Nếu bạn đang cố gắng so sánh một loạt các tệp, bạn sẽ đạt đến điểm băm là câu trả lời tốt hơn nếu các tệp nằm trên bộ lưu trữ quay.

Băm thực sự tỏa sáng khi bạn không có sẵn tất cả dữ liệu. Ví dụ, các tập tin trên các máy khác nhau. Nó cũng cho phép bạn lưu kết quả tính toán và tham khảo chúng sau. (Báo cáo này có giống với báo cáo cũ không? Khi bạn tạo báo cáo lưu một hàm băm của nó. Khi bạn thực hiện báo cáo tiếp theo, bạn có thể chỉ cần so sánh các giá trị băm. Không chỉ bạn không cần phải đọc báo cáo cũ trong bạn không ' thậm chí cần phải có một bản sao của nó.)


0

Tôi nghĩ rằng bạn nên sử dụng tiện ích so sánh tệp được cung cấp với hệ điều hành của mình hoặc sử dụng công cụ so sánh tệp (xem: công cụ so sánh tệp wiki ) để so sánh nội dung SAU KHI bạn đã kiểm tra các thuộc tính tệp được nêu ra bởi @Glenn Nelson.

Tôi không nghĩ rằng CRC chính xác 100% và tôi nghĩ rằng độ chính xác của nó giảm theo chiều dài tập tin. Ngoài ra, tôi không khuyên bạn nên viết nó từ đầu vì nó có thể yêu cầu nhiều thử nghiệm.


0

Có nhất thiết phải đọc từng byte đơn để kiểm tra xem một tệp được sao chép có giống với bản gốc không? CÓ để chắc chắn 100%

Có nhất thiết phải đọc từng byte đơn để kiểm tra xem một tệp đã sao chép KHÔNG trùng với bản gốc không? KHÔNG

Do đó, để nhanh chóng xác định sự không đồng nhất, trước tiên hãy kiểm tra siêu dữ liệu như kích thước tệp và bất kỳ loại tổng kiểm tra / CRC hoặc MIME nào mà hệ điều hành / hệ thống tệp / cửa hàng có thể đang duy trì . Vì chúng được hệ thống đó tính toán trước, bạn không phải trả chi phí này tại thời điểm so sánh.

Nếu thử nghiệm đó vượt qua, bạn vẫn cần so sánh từng byte riêng lẻ nếu bạn cần chắc chắn 100%, NHƯNG LƯU Ý rằng trong các CPU có đường ống hiện đại và sử dụng nhiều luồng và có thể nhiều bộ xử lý / CPU, thực hiện so sánh khối các tệp lớn là THỰC SỰ nhanh và hiệu quả vì quá trình này rất song song. Nhanh hơn bất kỳ loại tính toán toán học nào liên quan đến từng byte (mặc dù một số thuật toán có thể cũng có thể song song hóa, nhưng có lẽ không dễ dàng hoặc quá tốt). Đó là bởi vì các CPU được tạo đường ống có thể thực hiện các hoạt động so sánh khối của bộ nhớ trong vi mã hoặc thậm chí phần cứng (rất nhanh) và các hệ thống con từ đĩa đến bộ nhớ được tối ưu hóa cao để đưa các khối tệp lớn đến / từ bộ nhớ, tất cả được thực hiện song song và với phần cứng. Nếu ứng dụng của bạn thực hiện loại điều này thường xuyên và đó là một nút cổ chai hiệu năng đã biết, bạn nên khôn ngoan triển khai mã này trong mã đa luồng được viết tốt, tận dụng các tiện ích song song của hệ điều hành và phần cứng của bạn (có thể sử dụng ngôn ngữ được thiết kế cho điều này).

Chỉ khi bạn muốn xử lý mỗi tệp một lần và thực hiện nhiều so sánh sau (trong đó bạn nhớ ["bộ đệm"] được tóm tắt hoặc "nén" [như JohnFX đưa ra] kết quả phân tích), sẽ có một lợi ích đáng kể khi làm như vậy, và thậm chí sau đó, chỉ để chứng minh sự khác biệt (có khả năng); để chứng minh tính đồng nhất, bạn vẫn cần thực hiện so sánh theo từng byte.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.