【问题标题】:Equivalent to Unix cksum in Windows相当于 Windows 中的 Unix cksum
【发布时间】:2011-10-03 10:25:38
【问题描述】:

我下载了一个文件和他的校验和(由 cksum Unix 命令生成)。

所以,我想在我的 C# 应用程序测试中校验和是否与我下载的应用程序足够。

我查看了 chsum 的 Unix 手册页:

  The cksum command calculates and prints to standard output a checksum
  for each named file, the number of octets in the file and the
  filename.

  cksum uses a portable algorithm based on a 32-bit Cyclic Redundancy
  Check.  This algorithm finds a broader spectrum of errors than the
  16-bit algorithms used by sum (see sum(1)).  The CRC is the sum of the
  following expressions, where x is each byte of the file.

       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 + x^0

  The results of the calculation are truncated to a 32-bit value.  The
  number of bytes in the file is also printed.

所以我写了一个简单的程序来求和:

byte[] arr = File.ReadAllBytes(@"MyApp").ToArray();

int cksum = 0;

foreach (byte x in arr)
{
    cksum += (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 + x ^ 0);
}

但是校验和不一样,我该如何解决这个问题?

谢谢


编辑

1) 修改后的算法为:

uint cksum = 0;

foreach (byte b in arr)
{
    var x = (uint)b;

    cksum += (IntPow(x, 32)
        + IntPow(x, 26) + IntPow(x, 23) + IntPow(x, 22)
        + IntPow(x, 16) + IntPow(x, 12) + IntPow(x, 11) + IntPow(x, 10)
        + IntPow(x, 8) + IntPow(x, 7) + IntPow(x, 5) + IntPow(x, 4) + IntPow(x, 2) + IntPow(x, 1) + IntPow(x, 0));
}

2) 我用class Crc32 : HashAlgorithm

给定一个 Crc32 为 2774111254 的 Unix 文件

  • 1) 给我:4243613712
  • 2) 给我:3143134679(种子为 0)

我做错了什么!?

【问题讨论】:

标签: c# checksum crc32


【解决方案1】:

在 C# 中,^ 符号是异或运算符。你想要函数Math.Pow

这给出了两个浮点数的优先级,在How do you do *integer* exponentiation in C#? 建议了替代方法

因此,您的代码将如下所示:

cksum += Math.pow(x,32) + Math.pow(x,26)

还要注意最后一条语句:

计算结果被截断为 32 位值。这 文件中的字节数也会被打印出来。

这是已签名 (int) 还是未签名 (uint)

您当然可以使用以下内容: http://www.codeproject.com/Articles/35134/How-to-calculate-CRC-in-C

【讨论】:

  • 我尝试了您的链接提供的课程,但结果不一样。 Unix:>cksum file2.exe :2774111254; Crc32.Compute(arr);: 1514701405 ;和以前的代码用 Pow 更正:4243613712。它们有什么不同?
【解决方案2】:

这些是权力,而不是异或。见Wikipedia about CRC

【讨论】:

    【解决方案3】:

    在 c# 中,^ 不是升幂运算符,而是 xor 运算符,而 CRC 是使用不特定于任何语言的通用数学术语编写的。

    也不要使用标准的“pow”函数,因为它们通常会使用浮点数来表示非常大的数字,例如 x^32。

    而您想要的是保持答案的 32 位。可能最好的方法是:

    • 编写您自己的整数幂函数,该函数将参数作为 Ints 并通过乘以 x N 次为您计算 x^N,并相信 .NET 运行时相当有效(或者如果它太慢,使用一些优化,例如通过平方进行取幂)。不要让数字变得太大,要么在每个倍数之后使用余数或按位与运算符四舍五入,要么使用未经检查的值并相信它们每次都回绕并保持低 32 位。
    • 查找直接计算 CRC32 的库或现有代码(例如,http://www.google.co.uk/search?q=c%23+crc32

    【讨论】:

      【解决方案4】:

      另见这个正确的实现https://cksum.codeplex.com/

      【讨论】:

        猜你喜欢
        • 2010-11-14
        • 2011-10-13
        • 2010-10-14
        • 2012-08-29
        • 2021-08-20
        • 2013-12-11
        • 2011-05-09
        • 2010-12-24
        • 2010-10-12
        相关资源
        最近更新 更多