가끔 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
C++Builder사용예
//C++Builder에서는 위에 BinToHexXX 함수들을 따로 pas 파일로 저장한후에
//C++Builder 프로젝트에 포함하시구
//다음과 같이 include해서 사용하시면 됩니다.
#include "uHexUtils.hpp"
void __fastcall TForm1::Button2Click(TObject *Sender)
{
if(OpenDialog1->Execute())
{
char outstr[3074];
char buf[1024];
int len;
int size=32;
int half=size/2;
TFileStream *fs = new TFileStream(OpenDialog1->FileName,0);
if(fs==NULL)return;
TStringList *lst=new TStringList;
len=fs->Read(buf,size);
while(len>0)
{
BinToHexEx2(buf,outstr,len,half);
lst->Add(String(outstr));
len=fs->Read(buf,size);
}
Memo1->Lines->Assign(lst);
lst->Free();
fs->Free();
}
}
//---------------------------------------------------------------------------
첨부파일은 아래그림과
그림이 나오는 C++Builder프로젝트입니다.
참조
http://cbuilder.borlandforum.com/impboard/impboard.dll?action=read&db=bcb_tip&no=362
http://cbuilder.borlandforum.com/impboard/impboard.dll?action=read&db=bcb_tip&no=785
그럼...