7

What is the best way to convert an array of bytes declared as TBytes to a RawByteString in Delphi 2009? This code actually works, maybe there is a faster way (without loop):

   function Convert(Bytes: TBytes): RawByteString; 
   var
     I: Integer;
   begin
     SetLength(Result, Length(Bytes));
     for I := 0 to ABytes - 1 do
       Result[I + 1] := AnsiChar(Bytes[I]);
   end;

4 Answers 4

17

The best way is this:

function Convert(const Bytes: TBytes): RawByteString; inline;
begin
  SetString(Result, PAnsiChar(pointer(Bytes)), length(Bytes));
end;

And don't forget to use const for Bytes parameters, for somewhat faster generated code.

7

The easiest way to convert bytes to a RawByteString is to use SetString().

Also, to avoid data loss if the RawByteString is ever assigned to other String types, you should assign a codepage to the RawByteString so that its character data gets converted correctly to the charset of the receiving String:

function Convert(const Bytes: TBytes): RawByteString; 
begin
  SetString(Result, PAnsiChar(PByte(Bytes))^, Length(Bytes));
  SetCodePage(Result, ..., False);
end;
2
  • I thought the point of using RawByteString is that it lacks codepage information in contrast to types like AnsiString or Utf8String.
    – blerontin
    Commented Sep 12, 2019 at 7:41
  • 3
    @blerontin RawByteString lacks a charset at compile time, but it inherits the runtime charset of whatever string is assigned to it. And a byte array has an implied charset to it, even if one is not carried in the byte payload itself. Like I said in my answer, RawByteString can be assigned to other string types, so it needs to carry a valid charset in its payload to facilitate proper assignments to avoid data loss Commented Sep 12, 2019 at 8:11
7

You could consider using move (untested)

function Convert(const Bytes: TBytes): RawByteString; 
begin
  SetLength(Result, Length(Bytes));
  Move(Bytes[0], Result[1], Length(Bytes))  
end;

And use "const" for the parameter so the array is not copied twice.

1
  • 1
    SetLength() will call ReallocMem to resize the existing RawByteString, so this version would perhaps unnecessary move() the previous data, without need, e.g. if you call this in a loop. SetString(Result,PAnsiChar(Bytes),length(Bytes) will be faster. Commented Jun 27, 2011 at 13:02
5

And remember to test:

IF Length(Bytes)>0 THEN MOVE.....

1
  • This should be a comment on the first (accepted) answer, I guess.
    – blerontin
    Commented Sep 12, 2019 at 7:44

Not the answer you're looking for? Browse other questions tagged or ask your own question.