Kontakt
DSVGO
Prüfsummen, insbesondere CRC32, bieten eine gute und einfache Möglichkeit, die Konsistenz etwa von Dateien zu prüfen. Wenn die CRC32-Summen zweier Dateien gleich sind, so werden die Dateien selbst auch zu 99,99999998% gleich sein.
Klar, dass der Vergleich zweier 32Bit-Zahlen viel schneller ist, als der Vergleich zweier Megabyte-Dateien. Vorneweg sollte man aber immer erst die Längen der beiden Dateien vergleichen (s.a. Artikel "Zwei Dateien vergleichen").
Gegenüber anderen Methoden der Prüfsummen-Bildung ist CRC ("Cyclic Redundancy Code") sehr robust sogar gegenüber Bit-Fehlern, die an der gleichen Stelle auftauchen. So heben sich "ein Bit zuviel" und "ein Bit zuwenig" in CRC nicht einfach auf, im Gegensatz zu der üblichen arithmetischen Summe "Module n".
Da CRC auf Bit-Ebene arbeitet (viele Shifts und Bit-Tests), ist eine reine Software-Lösung (nicht nur in VB) eigentlich nur sehr schwer zu realisieren und zudem ziemlich langsam. Doch zum Glück gibt es eine Möglichkeit, die CRC-Berechnung durch vorausberechnete Tabellen zu beschleunigen.
Weitere Informationen zu der dahintersteckenden Theorie der Berechnung sind u.a. in "A painless Guide to CRC Error Detection Algorithms" zu finden.
Die CRC32-Summe eines (Unicode-)Strings bestimmen:
MsgBox Hex$(CRC32Unicode("abcdefgh")) 'ergibt AEEF2A50
An eine Datei die CRC32-Summe dranhängen:
CRC32File "C:\Test\File.dat", Add:=True
Die CRC32-Summe einer Datei prüfen:
If CRC32File("C:\Test\File.dat", Check:=True) Then MsgBox "Datei OK" End If
Legen Sie am Besten ein neues Modul an, etwa "modCRC.Bas".
Im Modulkopf werden folgende Deklarationen (für die Speicherung der vorausberechneten Werte) benötigt:
Option Explicit Private pInititialized As Boolean Private pTable(0 To 255) As Long
Die folgende Prozedur muss nur einmal aufgerufen werden (erledigen die CRC-Funktionen selbstständig). Sie füllt die Hilfstabelle mit allen möglichen Byte-Werten zu einem vorgegebenen "Polynom":
Public Sub CRCInit( _ Optional ByVal Poly As Long = &HEDB88320 _ ) 'Deklarationen: Dim CRC As Long Dim i As Integer Dim j As Integer For i = 0 To 255 CRC = i For j = 0 To 7 If CRC And &H1 Then 'CRC = (CRC >>> 1) ^ Poly CRC = ((CRC And &HFFFFFFFE) \ &H2 And &H7FFFFFFF) Xor Poly Else 'CRC = (CRC >>> 1) CRC = CRC \ &H2 And &H7FFFFFFF End If Next j pTable(i) = CRC Next i pInititialized = True End Sub
Die folgende Funktion gibt entweder die CRC32-Summe zurück (falls Check=False, default), oder (bei Check=True) prüft das Byte-Array darauf, ob die letzten 4 Bytes gerade der CRC-Summe entsprechen:
' ©2003 by Jost Schwider, http://vb-tec.de/ Public Function CRC32( _ ByRef Bytes() As Byte, _ Optional ByVal Check As Boolean = False _ ) As Long 'Deklarationen: Dim CRC As Long Dim i As Long Dim n As Long If Not pInititialized Then CRCInit 'Daten-Länge bestimmen: n = UBound(Bytes) If Check Then n = n - 4 If n < LBound(Bytes) Then Exit Function End If 'CRC berechnen: CRC = &HFFFFFFFF For i = LBound(Bytes) To n 'CRC = (CRC >>> 8) ^ pTable[Bytes[i] ^ (CRC & 0xff)] CRC = ((CRC And &HFFFFFF00) \ &H100) And &HFFFFFF _ Xor pTable(Bytes(i) Xor CRC And &HFF&) Next i CRC32 = Not CRC If Check Then 'CRC checken: CRC = Bytes2Long(Bytes(i), Bytes(i + 1), Bytes(i + 2), Bytes(i + 3)) CRC32 = (CRC32 = CRC) End If End Function
Diese Funktion arbeitet analog zu CRC32, jedoch mit einem String als Eingabe:
Public Function CRC32Unicode( _ ByRef Text As String, _ Optional ByVal Check As Boolean = False _ ) As Long 'Wie Byte-Array behandeln: CRC32Unicode = CRC32(StrConv(Text, vbFromUnicode), Check) End Function
Diese Funktion arbeitet wie CRC32, jedoch mit einem Datei(pfad). Zusätzlich kann mit dem optionalen Parameter Add festgelegt werden, ob die Prüfsumme an die Datei angehängt werden soll:
' ©2003 by Jost Schwider, http://vb-tec.de/ Public Function CRC32File( _ ByRef Path As String, _ Optional ByVal Check As Boolean = False, _ Optional ByVal Add As Boolean = False _ ) As Long 'Deklarationen: Dim Buffer() As Byte Dim BufferSize As Long Dim CRC As Long Dim FileNr As Integer Dim Length As Long Dim i As Long If Not pInititialized Then CRCInit BufferSize = &H1000 '4 KB ReDim Buffer(1 To BufferSize) FileNr = FreeFile Open Path For Binary As #FileNr 'Daten-Länge bestimmen: Length = LOF(FileNr) If Check Then Length = Length - 4 If Length < 0 Then Exit Function End If 'CRC berechnen: CRC = &HFFFFFFFF Do While Length 'Buffer einlesen: If Length < BufferSize Then BufferSize = Length ReDim Buffer(1 To Length) End If Get #FileNr, , Buffer 'Buffer CRC-summieren: For i = 1 To BufferSize CRC = ((CRC And &HFFFFFF00) \ &H100) And &HFFFFFF _ Xor pTable(Buffer(i) Xor CRC And &HFF&) Next i Length = Length - BufferSize Loop CRC32File = Not CRC If Check Then 'CRC checken: Get #FileNr, , CRC If Add Then Put #FileNr, LOF(FileNr) - 3, CRC32File CRC32File = (CRC32File = CRC) Else If Add Then Put #FileNr, , CRC32File End If Close #FileNr End Function
Aus Performance-Gründen wird die Datei (im Gegensatz zu CRC32) Block-weise verarbeitet.
© Jost Schwider, 24.10.2002-24.10.2002 - http://vb-tec.de/crc.htm