Эквивалент Unix cksum в Windows - PullRequest
2 голосов
/ 12 июля 2011

Я загружаю файл и его контрольную сумму (генерируется командой Unix cksum).

Итак, я хочу, чтобы в моем тесте приложения на C # была ли контрольная сумма адекватна загруженному приложению.

Я проверил на man-странице Unix в chsum:

  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);
}

Но контрольные суммы не совпадают, как я могу это исправить?

Спасибо


EDIT

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

Учитывая файл Unix, где Crc32: 2774111254

  • 1) дает мне: 4243613712
  • 2) Дает мне: 3143134679 (с семенем 0)

Что я делаю не так!?

Ответы [ 4 ]

2 голосов
/ 12 июля 2011

В 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)
2 голосов
/ 12 июля 2011

В C # символ ^ является оператором исключающего или. Вы хотите функцию Math.Pow .

Это дает число двух чисел с плавающей запятой, альтернативы предлагаются на Как вы делаете * целочисленное * возведение в степень в 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

2 голосов
/ 12 июля 2011

Это силы, а не ксоры. См. Википедия о CRC .

0 голосов
/ 07 октября 2014

Также см. Эту правильную реализацию https://cksum.codeplex.com/

...