cara mengonversi array byte ke representasi hexnya di Delphi

Saya memiliki variabel TBytes dengan nilai [0,0,15,15]. Bagaimana cara mengubahnya menjadi "00FF"?

Saya tidak ingin menggunakan loop, karena logika ini digunakan dalam fungsi intensif waktu.

(Saya mencoba menggunakan BinToHex, tapi saya tidak bisa membuatnya berfungsi dengan variabel string.)

Terima kasih & Salam,

Pavan.


person Pavan    schedule 29.06.2009    source sumber


Jawaban (4)


// Swapping is necessary because x86 is little-endian.
function Swap32(value: Integer): Integer;
asm
  bswap eax
end;

function FourBytesToHex(const bytes: TBytes): string;
var
  IntBytes: PInteger;
  FullResult: string;
begin
  Assert(Length(bytes) = SizeOf(IntBytes^));
  IntBytes := PInteger(bytes);
  FullResult := IntToHex(Swap32(IntBytes^), 8);
  Result := FullResult[2] + FullResult[4] + FullResult[6] + FullResult[8];
end;

Jika baris terakhir terlihat sedikit aneh, itu karena Anda meminta array empat byte diubah menjadi string empat karakter, sedangkan dalam kasus umum, delapan digit heksadesimal diperlukan untuk mewakili empat- nilai byte. Saya hanya berasumsi bahwa nilai byte Anda semuanya di bawah 16, jadi hanya diperlukan satu digit heksadesimal. Jika contoh Anda salah ketik, ganti saja dua baris terakhir dengan yang ini:

Result := IntToHex(Swap32(IntBytes^), 8);

Omong-omong, persyaratan Anda yang melarang loop tidak akan terpenuhi. IntToHex menggunakan loop secara internal.

person Rob Kennedy    schedule 29.06.2009
comment
IntToHex(IntBytes^, 8); menghasilkan string dalam urutan terbalik. Jika Anda melihat pertanyaan saya, saya memerlukannya sebagai 00FF, tetapi fungsi di atas menghasilkannya sebagai FF00 .. Bisakah saya menentukan urutan byte? - person Pavan; 30.06.2009
comment
Hasil := Hasil Penuh[8] + Hasil Penuh[6] + Hasil Penuh[4] + Hasil Penuh[2]; - person Nosredna; 30.06.2009
comment
apakah ada cara untuk menentukan urutan byte alih-alih mengaksesnya elemen demi elemen..?? - person Pavan; 30.06.2009
comment
Maaf. Saya lupa bahwa x86 adalah little-endian, jadi Anda perlu menukar urutan byte. - person Rob Kennedy; 30.06.2009
comment
@Pavan: tidak bisakah Anda menambahkan parameter urutan byte boolean ke header fungsi, lalu menggunakan baris terakhir dari jawaban asli Rob dan komentar Nosredna sebagai alternatif dalam pernyataan if? - person Argalatyr; 30.06.2009

Yang ini cukup cepat dan berfungsi dengan ukuran array apa pun.. Ini seperti BinToHex, tetapi alih-alih mengharapkan nilai 0..255 byte, ia hanya menggunakan nibble rendah.

procedure BinToSingleHex(Buffer, Text: PAnsiChar; BufSize: Integer);
const
  Convert: array[0..15] of AnsiChar = '0123456789ABCDEF';
var
  I: Integer;
begin
  for I := 0 to BufSize - 1 do
  begin
    Text[0] := Convert[Byte(Buffer[I]) and $F];
    Inc(Text);
  end;
end;

Assembler yang melakukan hal yang sama:

procedure BinToSingleHex(Buffer, Text: PAnsiChar; BufSize: Integer);assembler;
asm
        PUSH    ESI
        PUSH    EDI
        MOV     ESI,EAX
        MOV     EDI,EDX
        MOV     EDX,0
        JMP     @@1
@@0:    DB      '0123456789ABCDEF'
@@1:    LODSB
        AND     DL,AL
        AND     DL,0FH
        MOV     AL,@@0.Byte[EDX]
        STOSB
        DEC     ECX
        JNE     @@1
        POP     EDI
        POP     ESI
end;

penggunaan:

type  THexDigit=0..15;
const ArSize=16;
var   Ar:array[0..Pred(ArSize)] of THexDigit=(0,1,2,3,4,5,6,7,8,9,8,7,6,5,4,3);
      S:Array[0..Pred(ArSize)] of AnsiChar;

BinToSingleHex(@Ar,S,Length(Ar));
WriteLn(S);
person Wouter van Nifterick    schedule 29.06.2009
comment
Awas. String hasil Anda tidak diakhiri dengan null. Selain itu, kode Anda memerlukan direktif kompiler @ operator yang diketik untuk dinonaktifkan karena Anda meneruskan penunjuk byte ke parameter yang mengharapkan penunjuk AnsiChar. Lebih baik ubah tipe parameter pertama menjadi PByte. Dan bagaimana menurut Anda bahwa Anda perlu menggunakan dan menghapus empat bit teratas di Delphi tetapi Anda tidak perlu melakukannya di assembler? - person Rob Kennedy; 30.06.2009
comment
Poin bagus.. dan ya, Anda benar.. tentu saja masih diperlukan untuk menutupi 4 bit paling signifikan di sana. perbaiki itu - person Wouter van Nifterick; 30.06.2009

Agak terlambat ke pesta tapi mengapa tidak tabel pencarian sederhana?

const
HexChars : Array[0..15] of Char = ('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F');

Dengan asumsi nilai TBytes 0..15

Function (ABytea: TBytes): string
    begin 
      Result  := HexChars[ABytea[0]];
      Result  := Result + HexChars[ABytea[1]];
      Result  := Result + HexChars[ABytea[2]];
      Result  := Result + HexChars[ABytea[3]];
    end;

tentu saja lebih rapi dengan loop :) dan perlu diubah untuk nilai byte di atas 15:

begin 
  Result  := HexChars[ABytea[0] shr 4];
  Result  := Result + HexChars[ABytea[0] and $0F];
  Result  := Result + HexChars[ABytea[1] shr 4];
  Result  := Result + HexChars[ABytea[1] and $0F];
  Result  := Result + HexChars[ABytea[2] shr 4];
  Result  := Result + HexChars[ABytea[2] and $0F];
  Result  := Result + HexChars[ABytea[3] shr 4];
  Result  := Result + HexChars[ABytea[3] and $0F];
end;

Masih lebih rapi dengan loop terutama jika TBytes semakin besar

person Despatcher    schedule 02.07.2009

person    schedule
comment
itu adalah TBytes dan bukan satu byte.. dan saya tidak ingin menggunakan loop untuk menghitung setiap nilai. Jika saya tidak salah, logika Anda bekerja per byte.. - person Pavan; 30.06.2009
comment
Ini sepertinya solusi terbaik yang akan Anda dapatkan. Anda harus menggunakan loop di suatu tempat. Jika Anda ingin menggunakannya pada TBytes, bungkus ini dalam fungsi yang menggunakan TBytes dan ulangi, buat string keluaran satu byte pada satu waktu. - person Mason Wheeler; 30.06.2009
comment
Ini dapat disesuaikan dengan solusi tanpa perulangan. Jika Anda benar-benar peduli dengan persyaratan itu. - person Nosredna; 30.06.2009