firemonkey android crc16结果与Windows的delphi不匹配

时间:2019-07-18 10:04:03

标签: delphi firemonkey crc16

在两个不同的项目中,我需要使用crc16 checksum。一个在Windows中,另一个在android.i中,我为Windows使用了一个代码,并且运行良好。

showmessage(  bin2crc16(HexToBin('1234'))    );   //---> 0EC9

这里是用于风吹的功能

function Pow(i, k: Integer): Integer;
var
  j, Count: Integer;
begin
  if k>0 then j:=2
    else j:=1;
  for Count:=1 to k-1 do
    j:=j*2;
  Result:=j;
end;

function BinToDec(Str: string): Integer;
var
  Len, Res, i: Integer;
  Error: Boolean;
begin
  Error:=False;
  Len:=Length(Str);
  Res:=0;
  for i:=1 to Len do
    if (Str[i]='0')or(Str[i]='1') then
      Res:=Res+Pow(2, Len-i)*StrToInt(Str[i])
    else
    begin
      //MessageDlg('It is not a binary number', mtInformation, [mbOK], 0);
      Error:=True;
      Break;
    end;
  if Error=True then Result:=0
    else Result:=Res;
end;
//------------------------------------------------------------------------------
function CRC16CCITT(bytes: array of Byte): Word;
const
  polynomial = $1021;
var
  crc: Word;
  I, J: Integer;
  b: Byte;
  bit, c15: Boolean;
begin
  crc := $FFFF;
  for I := 0 to High(bytes) do
  begin
    b := bytes[I];
    for J := 0 to 7 do
    begin
      bit := (((b shr (7-J)) and 1) = 1);
      c15 := (((crc shr 15) and 1) = 1);
      crc := crc shl 1;
      if ((c15 xor bit) <> false) then crc := crc xor polynomial;
    end;
  end;
  Result := crc and $ffff;
end;
//------------------------------------------------------------------------------
function HexToDec(const Str: string): Integer;
begin
  if (Str <> '') and ((Str[1] = '-') or (Str[1] = '+')) then
    Result := StrToInt(Str[1] + '$' + Copy(Str, 2, MaxInt))
  else
    Result := StrToInt('$' + Str);
end;
//------------------------------------------------------------------------------
function bin2crc16(str: string): string;
var
I:integer;
lengthCount : integer;
crcByteArr : array of Byte;
crcOut : Word;
begin
  lengthCount := Trunc(length(str)/8);
  setlength(crcByteArr , lengthCount );
  for I := 0 to lengthCount-1 do
  begin
    crcByteArr[I] := BinToDec(copy(str, I*8+1, 8));
  end;
  crcOut := CRC16CCITT(crcByteArr);

  result := crcOut.ToHexString;

end;
//------------------------------------------------------------------------------
function HexToBin(Hexadecimal: string): string;
const
  BCD: array [0..15] of string =
    ('0000', '0001', '0010', '0011', '0100', '0101', '0110', '0111',
    '1000', '1001', '1010', '1011', '1100', '1101', '1110', '1111');
var
  i: integer;
begin
  Result := '';
  for i := Length(Hexadecimal) downto 1 do
    Result := BCD[StrToInt('$' + Hexadecimal[i])] + Result;
end;

但是对于Android,我更改了代码以处理零索引字符串。 结果不一样

memo2.Lines.Add( bin2crc16(HexToBin('1234')) ); //-----> 1AFa

此处是android中使用的功能

function BinToDec(Str: string): Integer;
var
  Len, Res, i: Integer;
  Error: Boolean;
begin
  Error:=False;
  Len:=Length(Str);
  Res:=0;
  for i:=0 to Len-1 do
    if (Str[i]='0')or(Str[i]='1') then
      Res:=Res+Pow(2, Len-i)*StrToInt(Str[i])
    else
    begin
      Error:=True;
      Break;
    end;
  if Error=True then Result:=0
    else Result:=Res;
end;
//------------------------------------------------------------------------------
function CRC16CCITT(bytes: array of Byte): Word;
const
  polynomial = $1021;
var
  crc: Word;
  I, J: Integer;
  b: Byte;
  bit, c15: Boolean;
begin
  crc := $FFFF;
  for I := 0 to High(bytes) do
  begin
    b := bytes[I];
    for J := 0 to 7 do
    begin
      bit := (((b shr (7-J)) and 1) = 1);
      c15 := (((crc shr 15) and 1) = 1);
      crc := crc shl 1;
      if ((c15 xor bit) <> false) then crc := crc xor polynomial;
    end;
  end;
  Result := crc and $ffff;
end;
//------------------------------------------------------------------------------
function bin2crc16(str: string): string;
var
I:integer;
lengthCount : integer;
crcByteArr : array of Byte;
crcOut : Word;
begin
  lengthCount := Trunc(length(str)/8);
  setlength(crcByteArr , lengthCount );
  for I := 0 to lengthCount-1 do
  begin
    crcByteArr[I] := BinToDec(copy(str, I*8, 8));
  end;
  crcOut := CRC16CCITT(crcByteArr);

  result := crcOut.ToHexString;

end;
//-----------------------------------------------------------------------------------
function HexToBin(Hexadecimal: string): string;
const
  BCD: array [0..15] of string =
    ('0000', '0001', '0010', '0011', '0100', '0101', '0110', '0111',
    '1000', '1001', '1010', '1011', '1100', '1101', '1110', '1111');
var
  i: integer;
begin
  Result := '';
  for i := Length(Hexadecimal)-1 downto 0 do
    Result := BCD[StrToInt('$' + Hexadecimal[i])] + Result;
end;
//---------------------------------------------------------------------------------
function Pow(i, k: Integer): Integer;
var
  j, Count: Integer;
begin
  if k>0 then j:=2
    else j:=1;
  for Count:=1 to k-1 do
    j:=j*2;
  Result:=j;
end;

我该如何解决我的问题!?

1 个答案:

答案 0 :(得分:0)

您还没有为零长度的字符串调整HexToBin函数。

BinToDec函数中还有一个问题。您的功率计算错误,因为字符串索引已更改。尽管您也可以在POW函数中调整索引,但可能最简单的处理方法如下:

function BinToDec(Str: string): Integer;
var
  Len, Res, i: Integer;
  Error: Boolean;
begin
  Error:=False;
  Len:=Length(Str);
  Res:=0;
  for i:=1 to Len do
    if (Str[I - 1]='0')or(Str[I - 1]='1') then
      Res:=Res+Pow(2, Len-i)*StrToInt(Str[I - 1])
    else
    begin
      Error:=True;
      Break;
    end;
  if Error=True then Result:=0
    else Result:=Res;
end;

要注意的最后一件事是,“复制”即使在基于零的字符串上也使用基于一的索引,但是您已假定它的索引为零。我同意这很令人困惑,但确实如此。