Delphi - BinToHex 和 HexToBin:反转

3

我希望将一个字节数组转换成十六进制字符串,并再次转换回字节数组。

以下是我使用的代码将其转换为十六进制字符串:

function bintoHex(const bin: array of byte): String;
const HexSymbols = '0123456789ABCDEF';
var i: integer;
begin
  SetLength(Result, 2*Length(bin));
  for i :=  0 to Length(bin)-1 do begin
    Result[1 + 2*i + 0] := HexSymbols[1 + bin[i] shr 4];
    Result[1 + 2*i + 1] := HexSymbols[1 + bin[i] and $0F];
  end;
end;

我不确定如何正确地将其转换回字节数组。 我希望得到以下结果:

Type TDCArray = Array of Byte;

function xHexToBin(const HexStr: String): TDCArray;
const HexSymbols = '0123456789ABCDEF';
var i: integer;
begin
  SetLength(Result, ???); //Need to now get half of the length, unsure how to go about that
  for i :=  0 to Length(HexStr)-1 do begin
    //Here convert back into an array somehow...
    //Result[i] := ???
  end;
end;

我该如何实现这个?此外,我正在使用Delphi XE2。

7
RTL具有HexToBin和BinToHex功能。 - Sertac Akyuz
4个回答

16

为什么不直接使用BinToHexHexToBin RTL函数?

{$APPTYPE CONSOLE}

uses
  System.Classes,
  System.SysUtils;

var
  LArray : array[1..6] of Byte = (10, 11, 12, 13, 14, 15);
  LText: string;
  I : integer;
begin
  try
    SetLength(LText, Length(LArray)*2);
    BinToHex(@LArray, PChar(LText), SizeOf(LArray));
    //show the hex string
    Writeln(LText);

    //fill the array with 0 
    FillChar(LArray, SizeOf(LArray), #0);

    //get the values from the hex string
    HexToBin(PChar(LText), @LArray, Length(LArray));

    //show the array values
    for i := 1 to Length(LArray) do
      Write(LArray[i]);
    Readln;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

请注意这些函数有一些怪癖,例如只支持小写字母。请仔细阅读文档 :) - Marc Durdin

4

2个十六进制字符代表1个字节。

我之前写的代码是伪代码,我希望你能理解我的意思。但如果你需要一些代码粘贴到这里,这里是实际实现:

program project1;

uses SysUtils,classes;


type
  TByteArray = array of byte;
function StrToArray(const Hexstr: String): TByteArray ;
var
i: Integer;
begin
SetLength(Result, Length(Hexstr) div 2);
for i:=0 to (Length(Hexstr) div 2 - 1) do
        Result[i]:= StrToInt('$' + Copy(Hexstr, (i * 2) + 1, 2));
end;


var
   arr : TByteArray;
   i : Integer;
begin
  arr := StrToArray('0A0B0C0D');
  for i:=0 to High(arr) do
          WriteLn(arr[i]);
  Readln;
end.   

顺便说一下,编码并不是简单的复制和粘贴;)


我在这一行代码上收到了“不兼容的类型:'Byte'和'string'”错误信息:Result[i]:= '$' + Copy(Hexstr, (i * 2) + 1, 2); - Josh Line
抱歉,没有编译器,请现在尝试。 - opc0de
我无法将函数类型设置为字节数组,当尝试运行该函数时,应用程序会崩溃。 :/ - Josh Line
有趣的事情是,我现在知道了。我学到了一些东西。我仍然在学习计算机科学。我才刚刚开始。仅仅因为我不知道答案就很悲哀吗?那么这里的每篇帖子都是“悲哀”的吗?我从回复中学到了东西,现在知道并理解了答案,你毫无理由地粗鲁是很悲哀的。我确实尝试了,谢谢。 - Josh Line

4

如果您想自己动手:

function xHexToBin(const HexStr: String): TBytes;
const HexSymbols = '0123456789ABCDEF';
var i, J: integer;
    B: Byte;
begin
  SetLength(Result, (Length(HexStr) + 1) shr 1);
  B:= 0;
  i :=  0;
  while I < Length(HexStr) do begin
    J:= 0;
    while J < Length(HexSymbols) do begin
      if HexStr[I + 1] = HexSymbols[J + 1] then Break;
      Inc(J);
    end;
    if J = Length(HexSymbols) then ; // error
    if Odd(I) then
      Result[I shr 1]:= B shl 4 + J
    else
      B:= J;
    Inc(I);
  end;
  if Odd(I) then Result[I shr 1]:= B;
end;

运行完美。我需要最终结果以Byte数组的形式呈现,所以我只需使用以下代码:"For i := 0 to length(arrTBytes) do arrofByte[i] := arrTBytes[i];" 谢谢。 - Josh Line
@JoshLine - TBytes 是 RTL 内置的 Byte 类型数组,你可以使用你的 TDCArray 替代它。 - kludg

0
unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  SysUtils, Forms, StdCtrls, ExtCtrls, Classes;

type

  { TTextToHex_HexToBin }

  TTextToHex_HexToBin = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    Edit2: TEdit;
    CheckTime: TImage;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
    procedure CheckTimeClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  end;

var
  TextToHex_HexToBin: TTextToHex_HexToBin;

implementation

{$R *.lfm}

{ TTextToHex_HexToBin }

//hex to binary

function HextoBinary(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;

procedure TTextToHex_HexToBin.Button1Click(Sender: TObject);

var
  TB: TBytes;
  WS: WideString;
  S:  string;
  i:  Integer;

begin
  WS := Trim(Edit1.Caption);
  TB := WideBytesOf(WS);

  // WideString to Hexadecimal
  S := '';
  for i := Low(TB) to High(TB) do
    S := S + IntToHex(TB[i], -1);
  Edit2.Caption :=Trim(S);

  // Hex to Binary

    Memo1.Caption:= HextoBinary(Trim(S));
end;

procedure TTextToHex_HexToBin.CheckTimeClick(Sender: TObject);
begin

end;

procedure TTextToHex_HexToBin.FormCreate(Sender: TObject);
begin

end;

end.

[以下是结果展示]


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接