创建一个函数以将十六进制值反转为字符串
Creating a function to reverse order a hex value as string
怎么放这个...
我一整天都在努力反转 Mifare NFC 卡的 UID 值,我读取的值是十六进制字符串,我可以将其转换为整数,这对 4 字节的 UID 非常有效。
当涉及到可以具有较大 UID 的 mifare desfire 卡示例时,事情变得一团糟:
04 44 44 22 E0 62 80
该值被正确读取,我什至可以使用我的函数 StrToInt('$' + TheUIDvalue) 将其转换为小数
现在奇怪的是我需要使用以下函数来反转它:
function HexToInt(s: string): Longword;
var
b: byte;
c: Char;
begin
Result := 0;
s := UpperCase(s);
for b := 1 to Length(s) do
begin
Result := Result * 16;
c := s[b];
case c of
'0' .. '9':
Inc(Result, Ord(c) - Ord('0'));
'A' .. 'F':
Inc(Result, Ord(c) - Ord('A') + 10);
else
begin
Result := 0
end;
end;
end;
end;
function LongEndian(L : UInt64) : UInt64;
begin
result := ((L and [=10=]0000FF) shl 24) or
((L and [=10=]00FF00) shl 8) or
((L and [=10=]FF0000) shr 8) or
((L and $FF000000) shr 24);
end;
function TfrmMain.HexResponseReversed ( input: string): string;
begin
result := IntToHex(EndianLong(hexToInt(input)));
end;
The result i get is :
80 62 E0 22
04 44 44 22 E0 62 80
所以这里严重遗漏了一些东西...请原谅乱七八糟的代码
我怀疑 IntToHex 函数有问题
您的 HexToInt()
函数 returns a LongWord
,因此其输出取决于平台。对于 64 位 POSIX 平台,如 Linux 和 iOS,它是 8 个字节,对于其他平台它是 4 个字节。
此外,尽管在 8 字节 UInt64
上运行,您的 LongEndian()
函数仅交换 4 个字节。
因此,您应该:
修复那些函数以在所有平台上对完整的 8 个字节进行操作,例如:
function HexToInt64(s: string): UInt64;
var
Len, I: Integer;
c: Char;
begin
Result := 0;
Len := Length(s);
if Len = 0 then Exit;
if Odd(Len) then
begin
s := '0' + s;
Inc(Len);
end;
if Len > 16 then Exit;
for I := 1 to Len do
begin
Result := Result * 16;
c := s[I];
case c of
'0' .. '9':
Inc(Result, Ord(c) - Ord('0'));
'A' .. 'F':
Inc(Result, Ord(c) - Ord('A') + 10);
'a' .. 'f':
Inc(Result, Ord(c) - Ord('a') + 10);
else
begin
Result := 0;
Exit;
end;
end;
end;
end;
function EndianLong(L : UInt64) : UInt64;
begin
Result := ((L and [=10=]000000000000FF) shl 56) or
((L and [=10=]0000000000FF00) shl 40) or
((L and [=10=]00000000FF0000) shl 24) or
((L and [=10=]000000FF000000) shl 8) or
((L and [=10=]0000FF00000000) shr 8) or
((L and [=10=]00FF0000000000) shr 24) or
((L and [=10=]FF000000000000) shr 40) or
((L and $FF00000000000000) shr 56);
end;
function TfrmMain.HexResponseReversed(input: string): string;
begin
Result := IntToHex(EndianLong(HexToInt64(input)));
end;
将单独的 HH
对十六进制字符串解码为字节数组,然后交换数组元素的顺序,然后从数组元素创建一个新的十六进制字符串:
uses
..., Classes;
function HexToBytes(s: string): TBytes;
var
Len: Integer;
begin
Result := nil;
Len := Length(s);
if Len = 0 then Exit;
if Odd(Len) then
begin
s := '0' + s;
Inc(Len);
end;
Len := Len div 2;
SetLength(Result, Len);
if HexToBin(PChar(s), PAnsiChar(PByte(Result)), Len) <> Len then
SetLength(Result, 0);
end;
function BytesToHex(Bytes: TBytes): string;
var
Len: Integer;
begin
Result := nil;
Len := Length(Bytes);
if Len = 0 then Exit;
SetLength(Result, Len * 2);
BinToHex(PAnsiChar(PByte(Bytes)), PChar(Result), Len);
end;
function EndianLong(Bytes : TBytes) : TBytes;
var
Len, I, J: Integer;
B: Byte;
begin
Result := nil;
Len := Length(Bytes);
if Len = 0 then Exit;
Result := Copy(Bytes, 0, Len);
if Len = 1 then Exit;
J := Pred(Len);
for I := 0 to Pred(Len div 2) do
begin
B := Result[I];
Result[I] := Result[J];
Result[J] := B;
Dec(J);
end;
end;
function TfrmMain.HexResponseReversed(input: string): string;
begin
Result := BytesToHex(EndianLong(HexToBytes(input)));
end;
也就是说,第三种选择是直接交换输入字符串的 HH
对,根本不将整个输入字符串转换为整数或字节数组:
uses
..., SysUtils;
function TfrmMain.HexResponseReversed(input: string): string;
const
HexDigits = ['0'..'9', 'A'..'F', 'a'..'f'];
var
Len, I: Integer;
P, Q: PChar;
Hex: array[0..1] of Char;
begin
Result := '';
Len := Length(input);
if Len = 0 then Exit;
Result := input;
if Odd(Len) then
begin
Result := '0' + Result;
Inc(Len);
end;
Len := Len div 2;
if Len = 1 then Exit;
UniqueString(Result);
P := PChar(Result);
Q := AnsiLastChar(Result);
Dec(Q);
For I := 1 to Len div 2 do
begin
Move(P^, Hex, SizeOf(Hex));
if not ((Hex[0] in HexDigits) and (Hex[1] in HexDigits)) then
begin
Result := '';
Exit;
end;
Move(Q^, P^, SizeOf(Hex));
Move(Hex, Q^, SizeOf(Hex));
Inc(P, 2);
Dec(Q, 2);
end;
end;
怎么放这个...
我一整天都在努力反转 Mifare NFC 卡的 UID 值,我读取的值是十六进制字符串,我可以将其转换为整数,这对 4 字节的 UID 非常有效。
当涉及到可以具有较大 UID 的 mifare desfire 卡示例时,事情变得一团糟:
04 44 44 22 E0 62 80
该值被正确读取,我什至可以使用我的函数 StrToInt('$' + TheUIDvalue) 将其转换为小数
现在奇怪的是我需要使用以下函数来反转它:
function HexToInt(s: string): Longword;
var
b: byte;
c: Char;
begin
Result := 0;
s := UpperCase(s);
for b := 1 to Length(s) do
begin
Result := Result * 16;
c := s[b];
case c of
'0' .. '9':
Inc(Result, Ord(c) - Ord('0'));
'A' .. 'F':
Inc(Result, Ord(c) - Ord('A') + 10);
else
begin
Result := 0
end;
end;
end;
end;
function LongEndian(L : UInt64) : UInt64;
begin
result := ((L and [=10=]0000FF) shl 24) or
((L and [=10=]00FF00) shl 8) or
((L and [=10=]FF0000) shr 8) or
((L and $FF000000) shr 24);
end;
function TfrmMain.HexResponseReversed ( input: string): string;
begin
result := IntToHex(EndianLong(hexToInt(input)));
end;
The result i get is :
80 62 E0 22
04 44 44 22 E0 62 80
所以这里严重遗漏了一些东西...请原谅乱七八糟的代码
我怀疑 IntToHex 函数有问题
您的 HexToInt()
函数 returns a LongWord
,因此其输出取决于平台。对于 64 位 POSIX 平台,如 Linux 和 iOS,它是 8 个字节,对于其他平台它是 4 个字节。
此外,尽管在 8 字节 UInt64
上运行,您的 LongEndian()
函数仅交换 4 个字节。
因此,您应该:
修复那些函数以在所有平台上对完整的 8 个字节进行操作,例如:
function HexToInt64(s: string): UInt64; var Len, I: Integer; c: Char; begin Result := 0; Len := Length(s); if Len = 0 then Exit; if Odd(Len) then begin s := '0' + s; Inc(Len); end; if Len > 16 then Exit; for I := 1 to Len do begin Result := Result * 16; c := s[I]; case c of '0' .. '9': Inc(Result, Ord(c) - Ord('0')); 'A' .. 'F': Inc(Result, Ord(c) - Ord('A') + 10); 'a' .. 'f': Inc(Result, Ord(c) - Ord('a') + 10); else begin Result := 0; Exit; end; end; end; end; function EndianLong(L : UInt64) : UInt64; begin Result := ((L and [=10=]000000000000FF) shl 56) or ((L and [=10=]0000000000FF00) shl 40) or ((L and [=10=]00000000FF0000) shl 24) or ((L and [=10=]000000FF000000) shl 8) or ((L and [=10=]0000FF00000000) shr 8) or ((L and [=10=]00FF0000000000) shr 24) or ((L and [=10=]FF000000000000) shr 40) or ((L and $FF00000000000000) shr 56); end; function TfrmMain.HexResponseReversed(input: string): string; begin Result := IntToHex(EndianLong(HexToInt64(input))); end;
将单独的
HH
对十六进制字符串解码为字节数组,然后交换数组元素的顺序,然后从数组元素创建一个新的十六进制字符串:uses ..., Classes; function HexToBytes(s: string): TBytes; var Len: Integer; begin Result := nil; Len := Length(s); if Len = 0 then Exit; if Odd(Len) then begin s := '0' + s; Inc(Len); end; Len := Len div 2; SetLength(Result, Len); if HexToBin(PChar(s), PAnsiChar(PByte(Result)), Len) <> Len then SetLength(Result, 0); end; function BytesToHex(Bytes: TBytes): string; var Len: Integer; begin Result := nil; Len := Length(Bytes); if Len = 0 then Exit; SetLength(Result, Len * 2); BinToHex(PAnsiChar(PByte(Bytes)), PChar(Result), Len); end; function EndianLong(Bytes : TBytes) : TBytes; var Len, I, J: Integer; B: Byte; begin Result := nil; Len := Length(Bytes); if Len = 0 then Exit; Result := Copy(Bytes, 0, Len); if Len = 1 then Exit; J := Pred(Len); for I := 0 to Pred(Len div 2) do begin B := Result[I]; Result[I] := Result[J]; Result[J] := B; Dec(J); end; end; function TfrmMain.HexResponseReversed(input: string): string; begin Result := BytesToHex(EndianLong(HexToBytes(input))); end;
也就是说,第三种选择是直接交换输入字符串的 HH
对,根本不将整个输入字符串转换为整数或字节数组:
uses
..., SysUtils;
function TfrmMain.HexResponseReversed(input: string): string;
const
HexDigits = ['0'..'9', 'A'..'F', 'a'..'f'];
var
Len, I: Integer;
P, Q: PChar;
Hex: array[0..1] of Char;
begin
Result := '';
Len := Length(input);
if Len = 0 then Exit;
Result := input;
if Odd(Len) then
begin
Result := '0' + Result;
Inc(Len);
end;
Len := Len div 2;
if Len = 1 then Exit;
UniqueString(Result);
P := PChar(Result);
Q := AnsiLastChar(Result);
Dec(Q);
For I := 1 to Len div 2 do
begin
Move(P^, Hex, SizeOf(Hex));
if not ((Hex[0] in HexDigits) and (Hex[1] in HexDigits)) then
begin
Result := '';
Exit;
end;
Move(Q^, P^, SizeOf(Hex));
Move(Hex, Q^, SizeOf(Hex));
Inc(P, 2);
Dec(Q, 2);
end;
end;