【问题标题】:How do I convert an array of bytes to string with Delphi?如何使用 Delphi 将字节数组转换为字符串?
【发布时间】:2020-11-23 20:22:47
【问题描述】:

我正在用 Delphi 开发一个项目,我想将字节数组转换为字符串类型。我该怎么办?

示例 C# 代码:

private void ListenerOnDataTransmit(DataTransmitEventArgs e)
{
    transmittedMsg = BitConverter.ToString(e.TransmittedBytes, 0, e.TransmittedBytes.Length);
    try { Invoke(new EventHandler(UpdateTransmittedMessagesListView)); }
    catch { }
}

【问题讨论】:

  • 您忘了告诉我们“将字节数组转换为字符串”是什么意思。有几种不同的解释,都是合理的:(1)把字节数组当作ASCII,获取它编码的文本; (2) 将字节数组视为UTF8,获取其编码的文本; (3) 获取数组的原始十六进制数据表示; (4) 获取数组的原始二进制数据表示;等等。在后一种情况下,您要对数字进行分组吗?

标签: delphi delphi-7


【解决方案1】:

BitConverter.ToString() 方法“将指定字节数组的每个元素的数值转换为其等效的十六进制字符串表示形式。”您可以在 Delphi 7 中通过在循环中使用 SysUtils.IntToHex() 函数手动执行相同的操作,例如:

uses
  ..., SysUtils;

var
  bytes: array of byte;
  s: string;
  i: Integer;
begin
  bytes := ...;
  s := '';
  if bytes <> nil then
  begin
    s := IntToHex(bytes[0], 2);
    for i := 1 to High(bytes) do
      s := s + '-' + IntToHex(bytes[i], 2);
  end;
end;

【讨论】:

  • 完全有效,但由于字符串的不断重新分配,对于长缓冲区(非常)低效。
  • @AndreasRejbrand 是的,有很多不同的方法可以解决这个问题。以上只是一个例子。
  • 是的。对于小缓冲区,它当然已经足够好了,所以 +1。
  • 至少现在我们得到了一个非常好的问答,我们可以将其用作关闭重复项的规范。
  • @RemyLebeau 谢谢,我在找这个。
【解决方案2】:

我怀疑你想要一个函数,它接受一个字节数组(或一个指向字节的原始指针)并返回一个包含十六进制形式数据的字符串。

我总是使用以下例程来执行此操作:

function BytesToString(ABuf: PByte; ALen: Cardinal): string; overload;
const
  HexDigits: array[0..$F] of Char = '0123456789ABCDEF';
var
   i: Integer;
begin
   if ALen = 0 then
   begin
     Result := '';
     Exit;
   end;
   SetLength(Result, 3 * ALen - 1);
   Result[1] := HexDigits[ABuf^ shr 4];
   Result[2] := HexDigits[ABuf^ and $0F];
   for i := 1 to ALen - 1 do
   begin
     Inc(ABuf);
     Result[3*i + 0] := ' ';
     Result[3*i + 1] := HexDigits[ABuf^ shr 4];
     Result[3*i + 2] := HexDigits[ABuf^ and $0F];
   end;
end;

type
  TByteArray = array of Byte;

function BytesToString(ABytes: TByteArray): string; overload;
begin
  Result := BytesToString(PByte(ABytes), Length(ABytes));
end;

第一个重载采用原始指针和长度,而第二个重载采用动态字节数组。

这是一个非常快速的实现,因为我不使用字符串连接(这需要不断的堆重新分配)。


上面的代码是专门为旧的 Delphi 7 编译器和 RTL 编写的。现代版本看起来更像这样:

function BytesToString(ABuf: PByte; ALen: Cardinal): string; overload;
const
  HexDigits: array[0..$F] of Char = '0123456789ABCDEF';
var
   i: Integer;
begin
   if ALen = 0 then
    Exit('');
   SetLength(Result, 3 * ALen - 1);
   Result[1] := HexDigits[ABuf[0] shr 4];
   Result[2] := HexDigits[ABuf[0] and $0F];
   for i := 1 to ALen - 1 do
   begin
     Result[3*i + 0] := ' ';
     Result[3*i + 1] := HexDigits[ABuf[i] shr 4];
     Result[3*i + 2] := HexDigits[ABuf[i] and $0F];
   end;
end;

function BytesToString(ABytes: TArray<Byte>): string; overload;
begin
  Result := BytesToString(PByte(ABytes), Length(ABytes));
end;

上述代码使用空格字符对每个字节进行分组。当然,您可能不希望这样做,但不分组是一项更简单的任务,因此我将其留作练习。

【讨论】:

  • 说实话,看到3 * ALen的时候真的是摸不着头脑……也就是说,直到看到空格为止。
  • IIRC, PByte-based ptr math 在 Delphi 7 中不可用,所以我用一些更老的方法替换它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-05-08
  • 2015-08-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多