「123あいう亜意卯」のような文章を「31 32 33 82 A0 82 A2 82 A4 88 9F 88 D3 89 4B」のように16進数に変換するにはどのようにすればいいのでしょうか?
勉強のため、できればそれぞれの処理の解説もお願いしたいです。
どなたかご教授お願いします。
この手の物は調べれば結構ありますよ。
下記ページのDelphiの所参考になります?
http://www.threeweb.ad.jp/~satou/string.htm
単純に変換したいのであれば、1文字ずつ文字を取り出し、文字(Char)を数値(Byte)に変換し、それを2桁の16進数に変換していけばOKです。
procedure TForm1.Button1Click(Sender: TObject);
var
S1: String;
S2: String;
i: Integer;
dd: Integer;
ds: Cardinal;
de: Cardinal;
begin
ds := GetTickCount; //デバッグ用:処理時間計測開始
for dd := 1 to 2000 do //デバッグ用:繰り返し実行しないと差がわからないので
begin
//変数の初期化
S1 := '123あいう亜意卯';
S2 := '';
//1文字目から順に文字列の長さ分処理する
for i := 1 to Length(S1) do
begin
//1文字抜き出して文字コードを取得し、16進数に変換
S2 := S2 + IntToHex(Ord(S1[i]), 2) + ' ';
end;
end;
Edit1.Text := Copy(S2, 1, Length(S2) - 1);
//以下、処理時間計測用
de := GetTickCount;
Memo1.Lines.Add('Test1:' + IntToStr(de - ds) + 'ms');
end;
別解は以下の通り。
人によっていろいろ書き方が違います。きっと。
procedure TForm1.Button2Click(Sender: TObject);
const
//定数として'0'〜'F'の配列を用意
HexStr: array[0..15] of char = '0123456789ABCDEF';
var
S1: String;
S2: String;
B: PBYTE;
C: PCHAR;
dd: Integer;
ds: Cardinal;
de: Cardinal;
begin
ds := GetTickCount; //デバッグ用:処理時間計測開始
for dd := 1 to 2000 do //デバッグ用:繰り返し実行しないと差がわからないので
begin
//変数の初期化
S1 := '123あいう亜意卯';
B := PBYTE(S1); //文字列の最初の位置のポインタを初期化(数値としてみるのでBYTE型)
SetLength(S2, Length(S1) * 3 - 1); //格納する文字列の大きさを初期化
C := PCHAR(S2); //変換後の文字列の最初の位置のポインタを初期化(こっちはCHAR型)
//文字列の終端は 0 なので 0 でない間続ける
while B^ <> 0 do
begin
//16進数の1文字目。16で割るより、右にシフトしたほうが早い
C^ := HexStr[B^ shr 4];
Inc(C);
//16進数の2文字目。16で割ったあまりより、論理和で出した方が早い
C^ := HexStr[B^ and 15];
Inc(C);
//半角スペースで区切る
C^ := ' ';
Inc(C);
//元の文字列のポインタを1つ進める
Inc(B);
end;
end;
Edit1.Text := S2;
de := GetTickCount;
Memo1.Lines.Add('Test2:' + IntToStr(de - ds) + 'ms');
end;
>Ruさん
すいません。ありがとうございます。
参考になります。
>にしのさん
ありがとうございます。
上のコードで理想の処理をすることができました。
丁寧な解説ありがとうございます。勉強になりました。
そして書き忘れてました。
この16進数を元の文字列に戻すにはどのように処理すればよいのでしょうか?
こっちは検索しても出てこなくて困っています。
度々すいません。
どなたかご教授お願いします。
Delphi7ではもっと便利な関数がありました。
ヘルプで、BinToHex、HexToBinを調べてみてください。
procedure TForm1.Button3Click(Sender: TObject);
var
S1: String;
S2: String;
i: Integer;
dd: Integer;
ds: Cardinal;
de: Cardinal;
begin
ds := GetTickCount; //デバッグ用:処理時間計測開始
for dd := 1 to 2000 do //デバッグ用:繰り返し実行しないと差がわからないので
begin
//変数の初期化
S1 := '123あいう亜意卯';
S2 := '';
SetLength(S2, Length(S1) * 2);
BinToHex(PCHAR(S1), PCHAR(S2), Length(S1));
end;
Edit1.Text := S2;//StrPas(PCHAR(S2));
//以下、処理時間計測用
de := GetTickCount;
Memo1.Lines.Add('Test1:' + IntToStr(de - ds) + 'ms');
end;
procedure TForm1.Button4Click(Sender: TObject);
var
S1: String;
S2: String;
i: Integer;
dd: Integer;
ds: Cardinal;
de: Cardinal;
begin
ds := GetTickCount; //デバッグ用:処理時間計測開始
for dd := 1 to 2000 do //デバッグ用:繰り返し実行しないと差がわからないので
begin
//変数の初期化
S1 := Edit1.Text;
S2 := '';
SetLength(S2, Length(S1) * 2);
HexToBin(PCHAR(S1), PCHAR(S2), Length(S1) div 2);
end;
Edit2.Text := S2;//StrPas(PCHAR(S2));
//以下、処理時間計測用
de := GetTickCount;
Memo1.Lines.Add('Test1:' + IntToStr(de - ds) + 'ms');
end;
>にしのさん
ありがとうございます。
さらに簡単に16進数にすることができました。
HexToBin関数ヘルプで見ました。
これでTextに16進数を入れてBufferに変換されたバイナリが入る、ということがわかったんですけど記述の仕方がさっぱりわかりません。
どのように記述すれば変数に変換した文字列が代入されるのでしょうか?
レベルの低い質問ばかりで申し訳ないです。
>これでTextに16進数を入れてBufferに変換されたバイナリが入る、ということがわかったんですけど記述の仕方がさっぱりわかりません。
>どのように記述すれば変数に変換した文字列が代入されるのでしょうか?
上のHexToBinのサンプルコードを実行すれば、変換されたバイナリ値(文字列)が変数S2に入るのは自分で確認できると思うけど?
それなのに、「記述の仕方がさっぱりわかりません」とはどういうこと?
せっかくの回答をもらいながら、それをよく読んでないんじゃない?。
(※サンプルコードのSetLength(S2, Length(S1) * 2);は、SetLength(S2, Length(S1) div 2);の間違いだけどね)
うわああああすいません。
よく読まずにBinToHexの内容かと勝手に思ってて最後までサンプルコード見てませんでした。
にしのさんすいません。本当に申し訳ございません。
>みえみえさん
ありがとうございます。これは明らかに自分の過失です。
迷惑をかけてしまってすいません。
今後は細心の注意を払って書き込みます。
皆様のおかげで無事解決することができました。
迷惑をかけてしまって本当に申し訳ないです。
ありがとうございました!
ツイート | ![]() |