Je travaille sur un système qui utilise une grande base de données MySQL et je dois calculer crc16 en fonction de certaines colonnes du tableau. Mais je ne trouve aucune fonction qui m'aide. MySQL n'a que crc32, mais j'ai besoin de CRC16 / ARC.

J'ai essayé de créer un code SQL pour calculer comment j'ai en Java et C # pour CRC16, mais sans succès.

Est-ce que quelqu'un peut m'aider? Je vous remercie!

--- Modifié --------------------

Le code en SQL de MySQL essaie ...

CREATE FUNCTION `fn_crc16`(pValue varchar(255)) RETURNS varchar(50) CHARSET utf8mb4
BEGIN
    declare retval, b binary;
    declare c char(1) default '';
    declare i, len integer default 0;
    set retval = 0x0000;
    set len = length(pValue);
    set i = 1;
    repeat
        set c = substring(pValue, i, 1);
        set b = (retval ^ cast(c as binary)) & 0xff;
        select value into b from tbl_crc16 where idx = b;
        set retval = b ^ (retval >> 8);
        set i = i + 1;
    until i > len end repeat;
    set retval = retval & 0xffff;
    return hex(retval);
END

Le tbl_crc16 est une liste de codes HEX.

Mes codes Java et C # génèrent la même valeur hexadécimale CRC 16.

Voici mon implémentation de CRC16 en Java pour Android.

public class Crc16 {
    static int[] table = {
            0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
            0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
            0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
            0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
            0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
            0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
            0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
            0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
            0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
            0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
            0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
            0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
            0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
            0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
            0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
            0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
            0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
            0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
            0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
            0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
            0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
            0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
            0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
            0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
            0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
            0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
            0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
            0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
            0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
            0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
            0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
            0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040,
    };

    public static String hash(String s) {
        byte[] bytes = s.getBytes();
        int crc16 = 0x0000;
        for (byte b : bytes)
            crc16 = table[(crc16 ^ b) & 0xff] ^ (crc16 >> 8);
        crc16 = crc16 & 0xFFFF;
        return Integer.toHexString(crc16);
    }
}
2
diegodsp 14 sept. 2020 à 22:04

2 réponses

Meilleure réponse

Cela implémente le CRC16 / modbus, sans avoir besoin d'utiliser une table

DELIMITER //
CREATE DEFINER=`root`@`%` FUNCTION `CRC16`( _STRING VARCHAR(25)) RETURNS varchar(50) CHARSET utf8mb4
    DETERMINISTIC
BEGIN
    DECLARE _myCRC integer;
    DECLARE _ord INTEGER;
    DECLARE _n Integer;
    DECLARE _m Integer;
    DECLARE _strlend Integer;
    SET _myCRC := x'FFFF';

      SET _n  := 1;  
      SET _strlend := LENGTH(_STRING) ;
      
        loop_crc:  LOOP
     
            IF  _n > _strlend THEN 
                LEAVE  loop_crc;
            END  IF;
              
            SET _ord := ORD(SUBSTRING(_STRING, _n, 1) );
            SET _myCRC :=  _myCRC ^ _ord;
            SET _m := 0;     
            loop_bit:  LOOP
                IF  _m = 8 THEN 
                    LEAVE  loop_bit;
                END  IF;
                IF (_myCRC & x'0001') = x'0001' THEN
                    SET _myCRC := (_myCRC >> 1) ^ x'A001';
                ELSE
                    SET _myCRC := _myCRC >> 1;        
                END IF;
                SET  _m := _m + 1;
            END LOOP;
            SET  _n := _n + 1;

        END LOOP;

      return HEX(_myCRC); 
 END//
DELIMITER ;

Requête SELECT CRC16("A");

Retour

CRC16("A")
707F

Vous pouvez vérifier le résultat sur https://crccalc.com/ ou utiliser vos propres résultats de java ou C #

2
nbk 15 sept. 2020 à 14:51

Si vous utilisez des varchars, selon votre fonction, cela fonctionnera:

declare retval, b, c integer;
declare i, len integer default 0;
set retval = 0x0000;
set len = length(pValue);
set i = 1;
repeat
    set c = ascii(substring(pValue, i, 1));
    set b = (retval ^ c) & 0xff;
    select value into b from tbl_crc16 where idx = b + 1; -- my idx starts at 1
    set retval = b ^ (retval >> 8);
    set i = i + 1;
until i > len end repeat;
set retval = retval & 0xffff;
return hex(retval);

Remarques:

  • l'idx de mon tbl_crc16 commence à 1; changez la condition where en idx = b si la vôtre commence à 0
  • binary type de données que vous utilisez pour retval et b est un type à un octet, c'est pourquoi cela n'a pas fonctionné; J'utilise des entiers

Exemple en direct via dbfiddle.uk, vérifie avec https://crccalc.com

3
MarcinJ 14 sept. 2020 à 22:18