Korzystam z iTextSharp, aby odczytać tekst z pliku PDF. Czasami jednak nie mogę wyodrębnić tekstu, ponieważ plik PDF zawiera tylko obrazy. Codziennie pobieram te same pliki PDF i chcę sprawdzić, czy plik PDF został zmodyfikowany. Jeśli nie można uzyskać tekstu i daty modyfikacji, czy suma kontrolna MD5 jest najbardziej wiarygodnym sposobem stwierdzenia, czy plik się zmienił?
Jeśli tak, niektóre próbki kodu byłyby mile widziane, ponieważ nie mam dużego doświadczenia z kryptografią.
Odpowiedzi:
Korzystanie z System.Security.Cryptography.MD5 jest bardzo proste :
(Uważam, że faktycznie wykorzystana implementacja MD5 nie musi być usuwana, ale prawdopodobnie i tak bym to zrobił).
To, jak porównasz wyniki później, zależy od ciebie; możesz na przykład przekonwertować tablicę bajtów na base64 lub bezpośrednio porównać bajty. (Pamiętaj tylko, że tablice się nie zastępują
Equals
. Korzystanie z base64 jest prostsze, ale nieco mniej wydajne, jeśli naprawdę chcesz porównać hasze).Jeśli chcesz przedstawić skrót jako ciąg, możesz go przekonwertować na szesnastkowy, używając
BitConverter
:źródło
BitConverter.ToString(md5.ComputeHash(stream)).Replace("-","").ToLower();
.Replace("-", String.Empty)
to lepsze podejście. Przeszedłem jednogodzinną sesję debugowania, ponieważ otrzymuję błędne wyniki podczas porównywania danych wejściowych użytkownika z skrótem pliku.Tak to robię:
źródło
using
bloków byłaby przydatna, ponieważ otwarcie pliku najprawdopodobniej zakończy się niepowodzeniem. Niepowodzenie wczesnego / szybkiego podejścia oszczędza zasoby potrzebne do utworzenia (i zniszczenia) instancji MD5 w takich scenariuszach. Możesz także pominąć nawiasy klamrowe pierwszegousing
i zapisać poziom wcięcia bez utraty czytelności.Wiem, że na to pytanie już udzielono odpowiedzi, ale używam tego:
Gdzie GetHash :
Prawdopodobnie nie najlepszy sposób, ale może się przydać.
źródło
public static String GetHash<T>(this Stream stream) where T : HashAlgorithm, new() { StringBuilder sb = new StringBuilder(); using (T crypt = new T()) { byte[] hashBytes = crypt.ComputeHash(stream); foreach (byte bt in hashBytes) { sb.Append(bt.ToString("x2")); } } return sb.ToString(); }
Oto nieco prostsza wersja, którą znalazłem. Czyta cały plik za jednym razem i wymaga tylko jednej
using
dyrektywy.źródło
ReadAllBytes
jest to, że ładuje cały plik do jednej tablicy. To w ogóle nie działa w przypadku plików większych niż 2 GiB i wywiera duży nacisk na GC, nawet w przypadku plików średnich. Odpowiedź Jona jest tylko nieco bardziej złożona, ale nie cierpi z powodu tych problemów. Wolę więc jego odpowiedź niż twoją.using
kolejności s bez pierwszych nawiasów klamrowychusing (var md5 = MD5.Create()) using (var stream = File.OpenRead(filename))
daje jedno użycie w linii bez niepotrzebnego wcięcia.using
dyrektywy”. nie był tak naprawdę dobrym powodem, aby wszystko odczytywać w pamięci. Bardziej efektywnym podejściem jest przesyłanie strumieniowe danychComputeHash
i, jeśli to możliwe,using
powinno się je stosować, ale całkowicie rozumiem, czy chcesz uniknąć dodatkowego poziomu wcięcia.Wiem, że jestem spóźniony na imprezę, ale przeprowadziłem test, zanim wdrożyłem rozwiązanie.
Zrobiłem test przeciwko wbudowanej klasie MD5, a także md5sum.exe . W moim przypadku wbudowana klasa zajęła 13 sekund, podczas gdy md5sum.exe również około 16-18 sekund przy każdym uruchomieniu.
źródło
A jeśli musisz obliczyć MD5, aby zobaczyć, czy pasuje on do MD5 obiektu blob platformy Azure, to to SO pytanie i odpowiedź może być pomocne: skrót MD5 obiektu blob przesłanego na platformę Azure nie pasuje do tego samego pliku na komputerze lokalnym
źródło