CRC32 in c#

来源:互联网 发布:数组push方法 编辑:程序博客网 时间:2024/05/02 01:21
If you need a CRC32 on a file or stream, here is some c# to do that: 

// program.cs
using System;
using System.Collections.Generic;
using System.Text; 

namespace CRC32


     
// Sample program to show usage of crc32 usage.  You can also pass a Stream.
    class Program
    {
        
static void Main(string[] args)
        {
            
try
            {
                
uint crc = Crc32.GetFileCRC32(@"c:windows otepad.exe");
                Console.WriteLine(
@"CRC32 of c:windows otepad.exe is: " + crc);
                Console.WriteLine(
"Hit Enter to exit.");
                Console.Read();
            }
            
catch ( Exception ex )
            {
                Console.WriteLine(ex.Message);
            }
        }
    }


// crc32.cs
using System;
using System.IO; 

namespace CRC32


    
/// <summary>
    
/// Modified from Mike Krueger's code.
    
/// Generate a table for a byte-wise 32-bit CRC calculation on the polynomial:
    
/// x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
    
///
    
/// Polynomials over GF(2) are represented in binary, one bit per coefficient,
    
/// with the lowest powers in the most significant bit.  Then adding polynomials
    
/// is just exclusive-or, and multiplying a polynomial by x is a right shift by
    
/// one.  If we call the above polynomial p, and represent a byte as the
    
/// polynomial q, also with the lowest power in the most significant bit (so the
    
/// byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
    
/// where a mod b means the remainder after dividing a by b.
    
///
    
/// This calculation is done using the shift-register method of multiplying and
    
/// taking the remainder.  The register is initialized to zero, and for each
    
/// incoming bit, x^32 is added mod p to the register if the bit is a one (where
    
/// x^32 mod p is p+x^32 = x^26++1), and the register is multiplied mod p by
    
/// x (which is shifting right by one and adding x^32 mod p if the bit shifted
    
/// out is a one).  We start with the highest power (least significant bit) of
    
/// q and repeat for all eight bits of q.
    
///
    
/// The table is simply the CRC of all possible eight bit values.  This is all
    
/// the information needed to generate CRC's on data a byte at a time for all
    
/// combinations of CRC register values and incoming bytes.
    
/// </summary>
    public sealed class Crc32
    {
        
#region Fields
        
private readonly static uint CrcSeed = 0xFFFFFFFF

        
private readonly static uint[] CrcTable = new uint[] {
   
0x000000000x770730960xEE0E612C0x990951BA0x076DC419,
   
0x706AF48F0xE963A5350x9E6495A30x0EDB88320x79DCB8A4,
   
0xE0D5E91E0x97D2D9880x09B64C2B0x7EB17CBD0xE7B82D07,
   
0x90BF1D910x1DB710640x6AB020F20xF3B971480x84BE41DE,
   
0x1ADAD47D0x6DDDE4EB0xF4D4B5510x83D385C70x136C9856,
   
0x646BA8C00xFD62F97A0x8A65C9EC0x14015C4F0x63066CD9,
   
0xFA0F3D630x8D080DF50x3B6E20C80x4C69105E0xD56041E4,
   
0xA26771720x3C03E4D10x4B04D4470xD20D85FD0xA50AB56B,
   
0x35B5A8FA0x42B2986C0xDBBBC9D60xACBCF9400x32D86CE3,
   
0x45DF5C750xDCD60DCF0xABD13D590x26D930AC0x51DE003A,
   
0xC8D751800xBFD061160x21B4F4B50x56B3C4230xCFBA9599,
   
0xB8BDA50F0x2802B89E0x5F0588080xC60CD9B20xB10BE924,
   
0x2F6F7C870x58684C110xC1611DAB0xB6662D3D0x76DC4190,
   
0x01DB71060x98D220BC0xEFD5102A0x71B185890x06B6B51F,
   
0x9FBFE4A50xE8B8D4330x7807C9A20x0F00F9340x9609A88E,
   
0xE10E98180x7F6A0DBB0x086D3D2D0x91646C970xE6635C01,
   
0x6B6B51F40x1C6C61620x856530D80xF262004E0x6C0695ED,
   
0x1B01A57B0x8208F4C10xF50FC4570x65B0D9C60x12B7E950,
   
0x8BBEB8EA0xFCB9887C0x62DD1DDF0x15DA2D490x8CD37CF3,
   
0xFBD44C650x4DB261580x3AB551CE0xA3BC00740xD4BB30E2,
   
0x4ADFA5410x3DD895D70xA4D1C46D0xD3D6F4FB0x4369E96A,
   
0x346ED9FC0xAD6788460xDA60B8D00x44042D730x33031DE5,
   
0xAA0A4C5F0xDD0D7CC90x5005713C0x270241AA0xBE0B1010,
   
0xC90C20860x5768B5250x206F85B30xB966D4090xCE61E49F,
   
0x5EDEF90E0x29D9C9980xB0D098220xC7D7A8B40x59B33D17,
   
0x2EB40D810xB7BD5C3B0xC0BA6CAD0xEDB883200x9ABFB3B6,
   
0x03B6E20C0x74B1D29A0xEAD547390x9DD277AF0x04DB2615,
   
0x73DC16830xE3630B120x94643B840x0D6D6A3E0x7A6A5AA8,
   
0xE40ECF0B0x9309FF9D0x0A00AE270x7D079EB10xF00F9344
   
0x8708A3D20x1E01F2680x6906C2FE0xF762575D0x806567CB,
   
0x196C36710x6E6B06E70xFED41B760x89D32BE00x10DA7A5A,
   
0x67DD4ACC0xF9B9DF6F0x8EBEEFF90x17B7BE430x60B08ED5,
   
0xD6D6A3E80xA1D1937E0x38D8C2C40x4FDFF2520xD1BB67F1,
   
0xA6BC57670x3FB506DD0x48B2364B0xD80D2BDA0xAF0A1B4C,
   
0x36034AF60x41047A600xDF60EFC30xA867DF550x316E8EEF,
   
0x4669BE790xCB61B38C0xBC66831A0x256FD2A00x5268E236,
   
0xCC0C77950xBB0B47030x220216B90x5505262F0xC5BA3BBE,
   
0xB2BD0B280x2BB45A920x5CB36A040xC2D7FFA70xB5D0CF31,
   
0x2CD99E8B0x5BDEAE1D0x9B64C2B00xEC63F2260x756AA39C,
   
0x026D930A0x9C0906A90xEB0E363F0x720767850x05005713,
   
0x95BF4A820xE2B87A140x7BB12BAE0x0CB61B380x92D28E9B,
   
0xE5D5BE0D0x7CDCEFB70x0BDBDF210x86D3D2D40xF1D4E242,
   
0x68DDB3F80x1FDA836E0x81BE16CD0xF6B9265B0x6FB077E1,
   
0x18B747770x88085AE60xFF0F6A700x66063BCA0x11010B5C,
   
0x8F659EFF0xF862AE690x616BFFD30x166CCF450xA00AE278,
   
0xD70DD2EE0x4E0483540x3903B3C20xA76726610xD06016F7,
   
0x4969474D0x3E6E77DB0xAED16A4A0xD9D65ADC0x40DF0B66,
   
0x37D83BF00xA9BCAE530xDEBB9EC50x47B2CF7F0x30B5FFE9,
   
0xBDBDF21C0xCABAC28A0x53B393300x24B4A3A60xBAD03605,
   
0xCDD706930x54DE57290x23D967BF0xB3667A2E0xC4614AB8,
   
0x5D681B020x2A6F2B940xB40BBE370xC30C8EA10x5A05DF1B
   
0x2D02EF8D
  }; 

        
private uint crc = 0// crc data checksum so far.
        #endregion 

        
#region Constructors
        
public Crc32()
        {
        }
        
#endregion 

        
#region Properties
        
/// <summary>
        
/// Returns the CRC32 data checksum computed so far.
        
/// </summary>
        public uint Value
        {
            
get
            {
                
return crc;
            }
            
set
            {
                crc 
= value;
            }
        }
        
#endregion 

        
#region Methods 

        
public static uint GetStreamCRC32(Stream stream)
        {
            
if ( stream == null )
                
throw new ArgumentNullException("stream");
            
if ( !stream.CanRead )
                
throw new ArgumentException("stream is not readable.");
            stream.Position 
= 0;
            Crc32 crc32 
= new Crc32();
            
byte[] buf = new byte[4096];
            
int len = 0;
            
while ( (len = stream.Read(buf, 0, buf.Length)) != 0 )
            {
                crc32.Update(buf, 
0, len);
            }
            stream.Position 
= 0;
            
return crc32.Value;
        } 

        
public static uint GetFileCRC32(string path)
        {
            
if ( path == null )
                
throw new ArgumentNullException("path"); 

            Crc32 crc32 
= new Crc32();
            
byte[] buf = new byte[4096];
            
int len = 0;
            
using ( FileStream fs = new FileStream(path, FileMode.Open) )
            {
                
while ( (len = fs.Read(buf, 0, buf.Length)) != 0 )
                {
                    crc32.Update(buf, 
0, len);
                }
            }
            
return crc32.Value;
        } 

        
/// <summary>
        
/// Resets the CRC32 data checksum as if no update was ever called.
        
/// </summary>
        public void Reset()
        {
            crc 
= 0;
        } 

        
/// <summary>
        
/// Updates the checksum with the int bval.
        
/// </summary>
        
/// <param name = "bval">
        
/// the byte is taken as the lower 8 bits of bval
        
/// </param>
        public void Update(int bval)
        {
            crc 
^= CrcSeed;
            crc 
= CrcTable[(crc ^ bval) & 0xFF^ (crc >> 8);
            crc 
^= CrcSeed;
        } 

        
/// <summary>
        
/// Updates the checksum with the bytes taken from the array.
        
/// </summary>
        
/// <param name="buffer">
        
/// buffer an array of bytes
        
/// </param>
        public void Update(byte[] buffer)
        {
            Update(buffer, 
0, buffer.Length);
        } 

        
/// <summary>
        
/// Adds the byte array to the data checksum.
        
/// </summary>
        
/// <param name = "buf">
        
/// the buffer which contains the data
        
/// </param>
        
/// <param name = "off">
        
/// the offset in the buffer where the data starts
        
/// </param>
        
/// <param name = "len">
        
/// the length of the data
        
/// </param>
        public void Update(byte[] buf, int off, int len)
        {
            
if ( buf == null )
            {
                
throw new ArgumentNullException("buf");
            } 

            
if ( off < 0 || len < 0 || off + len > buf.Length )
            {
                
throw new ArgumentOutOfRangeException();
            } 

            crc 
^= CrcSeed; 

            
while ( --len >= 0 )
            {
                crc 
= CrcTable[(crc ^ buf[off++]) & 0xFF^ (crc >> 8);
            } 

            crc 
^= CrcSeed;
        }
        
#endregion
    }