본문 바로가기

언어/delphi

BinToHexEx

출처: http://www.borlandforum.com/impboard/impboard.dll?action=read&db=bcb_tip&no=919 

가끔 Binary파일의 TMemo컴포넌트에 읽어오면 
왜 EditPlus나 다른 외부 에디터 처럼 Hex로 안보이냐는 질문이 올라오는 경우가 있다. 

당연한것을 .....    

이걸 모르는 이에게 설명하기란 참 쉽지 않는것 같다. 

여튼 그것을 설명하려는 것이 아니구... 


Binary를 Hex-String으로 변환해주는 VCL함수가 있다. 
Classes 유닛에 BinToHex 라고... 
그 반대 함수는 HexToBin 이라고 있다. 

 
 
procedure BinToHex(Buffer, Text: PChar; BufSize: Integer); assembler;
const
  Convert: array[0..15] of Char = '0123456789ABCDEF';
var
  I: Integer;
begin
  for I := 0 to BufSize - 1 do
  begin
    Text[0] := Convert[Byte(Buffer[I]) shr 4];
    Text[1] := Convert[Byte(Buffer[I]) and $F];
    Inc(Text, 2);
  end;
end;


그런데 위 BinToHex 는 Binary를 Hex-String으로 만들어 주기는 하는데... 
Byte길이만큼 모두 붙여서 만들어 준다. 

외부 Editer처럼 중간에 한칸 뛰우고싶은데.... 
[중간에 한칸 공백문자를 넣어주는 BinToHex] 

//BinToHex 함수에서 한칸씩 공백문자 넣는  기능 추가
procedure BinToHexEx(Buffer, Text: PChar; BufSize: Integer); assembler;
const
  Convert: array[0..15] of Char = '0123456789ABCDEF';
var
  I: Integer;
begin
  for I := 0 to BufSize - 1 do
  begin
    Text[0] := Convert[Byte(Buffer[I]) shr 4];
    Text[1] := Convert[Byte(Buffer[I]) and $F];
    Text[2] := ' ';
    Inc(Text, 3);
  end;
  Text[0] :=Char($0);
end;


음 그리고 위에 함수들은 모두 Hex-String이 대문자로만 표현된다. 
소문자 Hex-String 으로 표현하려면? 

//BinToHexEx 함수에서 소문자로 표시
procedure BinToHexExSmall(Buffer, Text: PChar; BufSize: Integer); assembler;
const
  Convert: array[0..15] of Char = '0123456789abcdef';
var
  I: Integer;
begin
  for I := 0 to BufSize - 1 do
  begin
    Text[0] := Convert[Byte(Buffer[I]) shr 4];
    Text[1] := Convert[Byte(Buffer[I]) and $F];
    Text[2] := ' ';
    Inc(Text, 3);
  end;
  Text[0] :=Char($0);
end;


외부 Editer를 보니 한라인의 중간쯤에 공백(space)를 좀더 둔것 같던데... 
라인 중간에 공백(space)추가 

//BinToHexEx 함수에서 Line의 중간에 space 추가
procedure BinToHexEx2(Buffer, Text: PChar; BufSize,Half: Integer); assembler;
const
  Convert: array[0..15] of Char = '0123456789ABCDEF';
var
  I: Integer;
begin
  if(BufSize>Half)then
  begin
    for I := 0 to Half - 1 do
    begin
      Text[0] := Convert[Byte(Buffer[I]) shr 4];
      Text[1] := Convert[Byte(Buffer[I]) and $F];
      Text[2] := ' ';
      Inc(Text, 3);
    end;
    Text[0] := ' ';
    Inc(Text, 1);
    for I := Half  to BufSize - 1 do
    begin
      Text[0] := Convert[Byte(Buffer[I]) shr 4];
      Text[1] := Convert[Byte(Buffer[I]) and $F];
      Text[2] := ' ';
      Inc(Text, 3);
    end;
    Text[0] :=Char($0);
  end
  else
  begin
   for I := 0 to BufSize - 1 do
    begin
      Text[0] := Convert[Byte(Buffer[I]) shr 4];
      Text[1] := Convert[Byte(Buffer[I]) and $F];
      Text[2] := ' ';
      Inc(Text, 3);
    end;
    Text[0] :=Char($0);
  end;
end;



------------------------------------------------------------ 

이제 위함수를 이용하여 File을 읽어와서 TMemo에 뿌려주는 코딩을 하면... 

procedure TForm1.Button2Click(Sender: TObject);
const
  size: Integer =32;
var
  fs: TFileStream;
  outstr: array [1..3074] of Char;
  buf: array [1..1024] of Char;
  str: String;
  len: Integer;
  lst: TStringList;
  half: Integer;
begin
  half:= size div 2 ;
  BinToHex
 
  if OpenDialog1.Execute() then
  begin
    fs:= TFileStream.Create(OpenDialog1.FileName,0);
    lst:= TStringList.Create;
    len:=fs.Read(buf,size);
    while(len<>0) do
    begin
      BinToHexEx2(@buf[1],@outstr[1],len,half);
      lst.Add(String(outstr));
      len:=fs.Read(buf,size);
    end;
    Memo1.Lines.Assign(lst);
    lst.free;
    fs.free;
  end;
end