首页 > 解决方案 > delphi 一种将十六进制字符串转换为二进制字符串的快速方法

问题描述

我必须像这样将十六进制字符串转换为二进制字符串

"F" -> "‭1111‬"
"A" -> "‭1010‬"
"1AF1" -> "1101011110001"

我有这个功能:

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; 

我这样称呼它:

for I := 0 to Trunc(tcpFrame.Length/100) do
begin
   str := copy(tcpFrame , (I*100)+1 , 100  );
   data  := data +  HexToBin( str );
end;

但这对于像 50-60 MB 字符串这样的大数据来说真的很慢

有没有更好更快的方法呢?

标签: delphi

解决方案


我认为主要问题是您一次将一个部分附加到字符串中。

在 Delphi 中,通过一次添加一个小部分来构建动态数组或字符串非常慢。更好的方法是将数组/字符串预先分配到一个较大的大小,然后填充其内容。如果一开始就知道最后的长度,就用这个尺寸;否则,分配大块。

在这种情况下,我们确实知道最终长度。

这个想法的一个示例实现:

function HexStrToBinStr(const AHexStr: string): string;
var
  i, j: Integer;
const
  HexParts: array[0..$F] of string =
    (
      {0} '0000',
      {1} '0001',
      {2} '0010',
      {3} '0011',
      {4} '0100',
      {5} '0101',
      {6} '0110',
      {7} '0111',
      {8} '1000',
      {9} '1001',
      {A} '1010',
      {B} '1011',
      {C} '1100',
      {D} '1101',
      {E} '1110',
      {F} '1111'
    );
begin
  SetLength(Result, 4 * AHexStr.Length);
  j := 1;
  for i := 1 to AHexStr.Length do
  begin
    case AHexStr[i] of
      '0'..'9':
        Move(HexParts[Ord(AHexStr[i]) - Ord('0')][1], Result[j], sizeof(char) * 4);
      'A'..'F':
        Move(HexParts[$A + Ord(AHexStr[i]) - Ord('A')][1], Result[j], sizeof(char) * 4);
      'a'..'f':
        Move(HexParts[$A + Ord(AHexStr[i]) - Ord('a')][1], Result[j], sizeof(char) * 4);
    else
      raise EConvertError.CreateFmt('Invalid hexadecimal string "%s".', [AHexStr]);
    end;
    Inc(j, 4);
  end;
end;

我不计算您的中间'$' + Hexadecimal[i]字符串和调用的事实StrToInt也可能会加快速度。

奖励练习:作为奖励练习,通过添加一个参数APrettyPrint: Boolean = False来修改此代码,如果True,则在每组四位之间添加一个空格。当然,您仍然应该预先分配。


推荐阅读