Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Converting Strings to Hex in a performant way

Tags:

delphi

I developed the following function to convert strings to hex values.

function StrToHex(const S: String): String;
const
  HexDigits: array[0..15] of Char = '0123456789ABCDEF';
var
  I: Integer;
  P1: PChar;
  P2: PChar;
  B: Byte;
begin

  SetLength(Result, Length(S) * 2);
  P1 := @S[1];
  P2 := @Result[1];

  for I := 1 to Length(S) do
  begin
    B := Byte(P1^);
    P2^ := HexDigits[B shr 4];
    Inc(P2);
    P2^ := HexDigits[B and $F];
    Inc(P1);
    Inc(P2);
  end; 

end; 

Now I was wondering whether there is a more efficient way to convert the strings?

like image 526
oopbase Avatar asked Jul 22 '10 10:07

oopbase


4 Answers

Depending on your Delphi version:

D5-D2007

uses classes;
function String2Hex(const Buffer: Ansistring): string;
begin
  SetLength(result, 2*Length(Buffer));
  BinToHex(@Buffer[1], @result[1], Length(Buffer));
end;

D2009+

uses classes;
function String2Hex(const Buffer: Ansistring): string;
begin
  SetLength(result, 2*Length(Buffer));
  BinToHex(@Buffer[1], PWideChar(@result[1]), Length(Buffer));
end;
like image 160
Uwe Raabe Avatar answered Nov 04 '22 12:11

Uwe Raabe


Try this one

   function String2Hex(const Buffer: Ansistring): string;
   var
     n: Integer;
   begin
     Result := '';
     for n := 1 to Length(Buffer) do
       Result := LowerCase(Result + IntToHex(Ord(Buffer[n]), 2));
   end;
like image 25
Bharat Avatar answered Nov 04 '22 12:11

Bharat


I know this is a very old topic, but I feel like I kinda need to share my code regarding the question. For years I use my own HexEncode, very similar with Forlan's code up there, but just today I found a faster way to encode Hex. With my old HexEncode, encoding a 180kb binary file took about 50 seconds, while with this function it took up 6 seconds.

function getHexEncode(txt : AnsiString) : AnsiString;
var
  a : integer ;
  st : TStringStream;
  buf : array [0..1] of AnsiChar;
  tmp : ShortString;
begin
  st := TStringStream.Create;
  st.Size := Length(txt)*2;
  st.Position := 0;
  for a:=1 to Length(txt) do
  begin
    tmp := IntToHex(Ord(txt[a]),2);
    buf[0] := tmp[1];
    buf[1] := tmp[2];
    st.Write(buf,2);
  end;
  st.Position := 0;
  Result := st.DataString;
  st.Free;
  //Result := '';  //my old code
  //for a:=1 to Length(txt) do Result := Result+IntToHex(Ord(txt[a]),2);  //my old code
end;
like image 43
Khaidir Mustafa Avatar answered Nov 04 '22 13:11

Khaidir Mustafa


It seems good enough, you could always have a byte->2 hex digits lookup table, but that (and similar optimizations) seems like overkill to me in most cases.

like image 32
Ofir Avatar answered Nov 04 '22 12:11

Ofir