【问题标题】:How do I calculate CRC32 of a string如何计算字符串的 CRC32
【发布时间】:2025-05-28 04:30:01
【问题描述】:

如何在 .NET 中计算字符串的 CRC32(循环冗余校验和)?

【问题讨论】:

    标签: .net crc32


    【解决方案1】:

    这家伙似乎有你的答案。

    https://damieng.com/blog/2006/08/08/calculating_crc32_in_c_and_net

    如果博客消失或破坏 url,这里是 github 链接:

    https://github.com/damieng/DamienGKit/blob/master/CSharp/DamienG.Library/Security/Cryptography/Crc32.cs


    博文中Crc32类的用法:

    Crc32 crc32 = new Crc32();
    String hash = String.Empty;
    
    using (FileStream fs = File.Open("c:\\myfile.txt", FileMode.Open))
      foreach (byte b in crc32.ComputeHash(fs)) hash += b.ToString("x2").ToLower();
    
    Console.WriteLine("CRC-32 is {0}", hash);
    

    【讨论】:

    • 很好的答案,该链接上的代码看起来很可靠。谢谢皮特!
    • 这段代码现在看起来已经被破坏了。 Crc32 类没有他的代码示例调用的基本构造函数。
    • 有一个 NuGet 包可以为您处理 Install-Package Crc32.NET。它实际上实现了算法(并且声称比其他替代方案快得多)。您可以运行上述 NuGet 命令或在 GitHub 上的 github.com/force-net/Crc32.NET 上找到源代码。我通常不会为每一件小事都包含依赖项,但这似乎是专业且合理的。
    【解决方案2】:

    由于您似乎希望计算字符串(而不是文件)的 CRC32,因此这里有一个很好的示例:https://rosettacode.org/wiki/CRC-32#C.23

    代码应该永远消失:

    /// <summary>
    /// Performs 32-bit reversed cyclic redundancy checks.
    /// </summary>
    public class Crc32
    {
        #region Constants
        /// <summary>
        /// Generator polynomial (modulo 2) for the reversed CRC32 algorithm. 
        /// </summary>
        private const UInt32 s_generator = 0xEDB88320;
        #endregion
    
        #region Constructors
        /// <summary>
        /// Creates a new instance of the Crc32 class.
        /// </summary>
        public Crc32()
        {
            // Constructs the checksum lookup table. Used to optimize the checksum.
            m_checksumTable = Enumerable.Range(0, 256).Select(i =>
            {
                var tableEntry = (uint)i;
                for (var j = 0; j < 8; ++j)
                {
                    tableEntry = ((tableEntry & 1) != 0)
                        ? (s_generator ^ (tableEntry >> 1)) 
                        : (tableEntry >> 1);
                }
                return tableEntry;
            }).ToArray();
        }
        #endregion
    
        #region Methods
        /// <summary>
        /// Calculates the checksum of the byte stream.
        /// </summary>
        /// <param name="byteStream">The byte stream to calculate the checksum for.</param>
        /// <returns>A 32-bit reversed checksum.</returns>
        public UInt32 Get<T>(IEnumerable<T> byteStream)
        {
            try
            {
                // Initialize checksumRegister to 0xFFFFFFFF and calculate the checksum.
                return ~byteStream.Aggregate(0xFFFFFFFF, (checksumRegister, currentByte) => 
                          (m_checksumTable[(checksumRegister & 0xFF) ^ Convert.ToByte(currentByte)] ^ (checksumRegister >> 8)));
            }
            catch (FormatException e)
            {
                throw new CrcException("Could not read the stream out as bytes.", e);
            }
            catch (InvalidCastException e)
            {
                throw new CrcException("Could not read the stream out as bytes.", e);
            }
            catch (OverflowException e)
            {
                throw new CrcException("Could not read the stream out as bytes.", e);
            }
        }
        #endregion
    
        #region Fields
        /// <summary>
        /// Contains a cache of calculated checksum chunks.
        /// </summary>
        private readonly UInt32[] m_checksumTable;
    
        #endregion
    }
    

    并使用它:

    var arrayOfBytes = Encoding.ASCII.GetBytes("The quick brown fox jumps over the lazy dog");
    
    var crc32 = new Crc32();
    Console.WriteLine(crc32.Get(arrayOfBytes).ToString("X"));
    

    您可以在这里测试输入/输出值:https://crccalc.com/

    【讨论】:

      【解决方案3】:

      使用上一个答案中的逻辑,这是我的看法:

      public class CRC32
      {
          private readonly uint[] ChecksumTable;
          private readonly uint Polynomial = 0xEDB88320;
      
          public CRC32()
          {
              ChecksumTable = new uint[0x100];
      
              for (uint index = 0; index < 0x100; ++index)
              {
                  uint item = index;
                  for (int bit = 0; bit < 8; ++bit)
                      item = ((item & 1) != 0) ? (Polynomial ^ (item >> 1)) : (item >> 1);
                  ChecksumTable[index] = item;
              }
          }
      
          public byte[] ComputeHash(Stream stream)
          {
              uint result = 0xFFFFFFFF;
      
              int current;
              while ((current = stream.ReadByte()) != -1)
                  result = ChecksumTable[(result & 0xFF) ^ (byte)current] ^ (result >> 8);
      
              byte[] hash = BitConverter.GetBytes(~result);
              Array.Reverse(hash);
              return hash;
          }
      
          public byte[] ComputeHash(byte[] data)
          {
              using (MemoryStream stream = new MemoryStream(data))
                  return ComputeHash(stream);
          }
      }
      

      【讨论】:

        最近更新 更多