Calculating CRC32 With VB
Demonstrates how to calculate CRC32 checksums using the same method as WinZip.
The CRC (Cyclic Redundancy Checksum) algorithm is a highly optimised and powerful way of checking whether a large number of bytes have been modified or not. The algorithm scans through all the bytes and generates a 32 bit number to represent the contents - small changes in the file contents result in large changes in the check sum, and there is a very low chance that two different streams of bytes will have the same CRC. This article provides a high performance class for generating a WinZip compatible CRC32 checksum in VB.
The CRC32 algorithm is a reliable way of checking whether an error has occurred in a sequence of bytes. There are various means of checking whether any bytes have been corrupted, for example, checksums and parity bits, but many simple schemes run a reasonably high chance of failing to detect an error depending on the type of corruption to the data that occurs. With CRC the chances of a corruption occurring which results in the same CRC are extremely remote.
An excellent description of the algorithm, and the various optimisations you can apply when implementing it (a fascinating and heavily mathematical process) is provided in Donald Knuth's classic programming series "The Art of Programming". You can find some online information here, although these do not cover the optimisation tricks in much detail (if at all):
The implementation here uses a pre-calculated lookup table to do a lot of the heavy work of generating the polynomial. Once this has been calculated then the actual algorithm becomes relatively simple, although it still causes some problems in VB. Here I must say thanks to Paul for providing the simple and fast version of the code that's now posted:
Calculating The Lookup Table
Private crc32Table() As Long Private Sub Class_initialize() ' This is the official polynomial used by CRC32 in PKZip. ' Often the polynomial is shown reversed (04C11DB7). Dim dwPolynomial As Long dwPolynomial = &HEDB88320 Dim i As Integer, j As Integer ReDim crc32Table(256) Dim dwCrc As Long For i = 0 To 255 dwCrc = i For j = 8 To 1 Step -1 If (dwCrc And 1) Then dwCrc = ((dwCrc And &HFFFFFFFE) \ 2&) And &H7FFFFFFF dwCrc = dwCrc Xor dwPolynomial Else dwCrc = ((dwCrc And &HFFFFFFFE) \ 2&) And &H7FFFFFFF End If Next j crc32Table(i) = dwCrc Next i End Sub
The CRC32 Calculation
Dim crc32Result As Long crc32Result = &HFFFFFFFF Dim i As Integer Dim iLookup As Integer [For Each [Byte] in [Buffer]] iLookup = (crc32Result And &HFF) Xor [Byte] crc32Result = ((crc32Result And &HFFFFFF00) \ &H100) _ And 16777215 ' nasty shr 8 with vb :/ crc32Result = crc32Result Xor crc32Table(iLookup) [Next] Crc32 = Not (crc32Result)
The result is a pretty quick algorithm: calculating CRC32 for a 70Mb file on an Athlon XP2000 machine took just a little more than a second. This compares favourably with around 0.65s for the C# version also available on the site.
Using the Class
The class provided wraps the details of determining CRC32 for a file or for an array of bytes. If you want to calculate CRC32 for a file, then you must use the cBinaryFileStream class which is provided as a source of the file data. This wraps standard VB file reading techniques so that a binary file can be read in chunks, which simplifies the CRC32 algorithm whilst still providing good performance. To use the cBinaryFileStream class simply create a new instance and set the File property to the file you want to read. Then you pass it into the GetFileCRC32 method of the cCRC32 class:
Dim cStream As New cBinaryFileStream cStream.File = txtFileName.Text Dim cCRC32 As New cCRC32 Dim lCRC32 As Long lCRC32 = cCRC32.GetFileCrc32(cStream)
You can also calculate the CRC32 of a byte array using the GetByteArrayCRC32 method.
This article provides a high performance CRC32 implementation for VB which can calculate a WinZip compatible CRC32 for files and data in VB memory.