Delphi Programming / Object Pascal
[掲載 2018年06月09日] [更新 2018年07月08日] Delphi 一般・その他 |
Move 関数によるバイトデータと文字または文字列の操作 |
動作確認等 |
Windows 7 U64(SP1) + Delphi XE5(UP2) Pro VCL-32 |
Move 関数によるバイトデータと文字または文字列の操作 |
Move 関数を使用した バイト配列と,Char 型の文字配列や文字列との変換関係のサンプルです. バイトデータを文字列に変換したり,文字列をバイトデータに変換するには TEncoding の機能を利用すれば簡単ですが,Move 関数も便利なことがあります.
サンプルで使用している関数名は Move ですが,実際にはバイト単位でのデータのコピーです.
これらの変換が必要な場面は,アプリケーションの処理の場面や状況によって異なります.したがって,Move 関数による変換が必ずしも適切というわけではありません.Move 関数の代わりに Windows API の CopyMemory 関数あるいは MoveMemory 関数も利用できます. |
[備考 1]
サンプルの中には,Move 関数の代わりに StrPCopy, StrCopy, StrPLCopy や StrLCopy 等の関数を使用しても変換あるいはコピーが可能なサンプルがあります.これらの Null 終端文字列のコピールーチンは,内部で Move 関数を使用して処理を行っています.
|
[備考 2]
TBytesStream, TStringStream にもバイト操作用のメソッドやプロパティが実装されています. |
01_バイト配列のデータと Char 型の文字配列データとの変換 |
バイト配列のデータを Char 型の文字配列のデータに変換するサンプルです.Char 型の文字配列のデータをバイト配列のデータにコピーする具体的なコードは掲載していませんが,Move 関数の引数を逆にすれば変換できます.
文字列をバイト配列に格納した後,Move 関数を使用してバイト配列のデータを Char 型の文字配列にコピーします.バイト配列が動的配列の場合と静的配列の場合,また,Char 型の動的配列と Char 型の静的配列の両方でテストしています,
Char 型の文字配列のデータを文字列として取り出すには,Null 終端の文字が必要です. |
|
図1
バイト配列のデータを Char 型の文字配列に変換 |
//=============================================================================
// バイト型配列のデータをChar型の文字配列のデータにする例
//
// テスト用の文字列をバイト型の配列データに格納
// そのバイト配列データをChar型の文字配列にコピーする
//
// TBytesはバイト型の動的配列
// TCharArrayはChar型の動的配列
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
LText : string;
LByteArr : TBytes;
LCharArrDst : TCharArray;
LByteSize : Integer;
LTextDst : string;
begin
Memo1.Lines.Clear;
//テスト用の文字列
LText := 'バイト配列データを Char 型の文字配列に' + sLineBreak
+ 'バイト配列 : 動的配列' + sLineBreak
+ 'Char 型配列 : 動的配列';
//バイト配列のサイズを設定して
//String型の文字列をバイト配列にコピー
LByteSize := Length(LText) * SizeOf(Char);
SetLength(LByteArr, LByteSize);
Move(LText[1], LByteArr[0], LByteSize);
//テスト用バイト配列データ作成終了
//バイト配列のデータをChar型の配列にコピー
//Null終端文字分を含めたサイズが必要
LByteSize := Length(LByteArr);
SetLength(LCharArrDst, LByteSize div SizeOf(Char) + SizeOf(Char));
Move(LByteArr[0], LCharArrDst[0], LByteSize);
//結果の表示
LTextDst := PChar(@LCharArrDst[0]);
Memo1.Lines.Add(LTextDst);
end;
//=============================================================================
// バイト型配列のデータをChar型の文字配列のデータにする例
//
// テスト用の文字列をバイト型の配列データに格納
// そのバイト配列データをChar型の文字配列にコピーする
//
// TByteArrayはバイト型の静的配列
// TCharArrayはChar型の動的配列
//
// 元のバイト配列が静的配列で初期化しているのでにNull終端文字分は不要
// ただし配列のサイズがNull終端分を含むサイズであること
//=============================================================================
procedure TForm1.Button2Click(Sender: TObject);
var
LText : string;
LByteArr : TByteArray;
LCharArrDst : TCharArray;
LByteSize : Integer;
LTextDst : string;
begin
Memo1.Lines.Clear;
//テスト用の文字列
LText := 'バイト配列データを Char 型の文字配列に' + sLineBreak
+ 'バイト配列 : 静的配列' + sLineBreak
+ 'Char 型配列 : 動的配列';
//バイト配列を初期化して
//String型の文字列をバイト配列にコピー
LByteSize := Length(LText) * SizeOf(Char);
FillChar(LByteArr, SizeOf(LByteArr), 0);
Move(LText[1], LByteArr[0], LByteSize);
//テスト用バイト配列データ作成終了
//バイト配列のデータをChar型の配列にコピー
LByteSize := Length(LByteArr);
SetLength(LCharArrDst, LByteSize div SizeOf(Char));
Move(LByteArr[0], LCharArrDst[0], LByteSize);
//結果の表示
LTextDst := PChar(@LCharArrDst[0]);
Memo1.Lines.Add(LTextDst);
end;
//=============================================================================
// バイト型配列のデータをChar型の文字配列のデータにする例
//
// テスト用の文字列をバイト型の配列データに格納
// そのバイト配列データをChar型の文字配列にコピーする
//
// TByteArrayはバイト型の静的配列
//=============================================================================
procedure TForm1.Button3Click(Sender: TObject);
var
LText : string;
LByteArr : TByteArray;
LCharArrDst : array [0..199] of Char;
LByteSize : Integer;
LTextDst : string;
begin
Memo1.Lines.Clear;
//テスト用の文字列
LText := 'バイト配列データを Char 型の文字配列に' + sLineBreak
+ 'バイト配列 : 静的配列' + sLineBreak
+ 'Char 型配列 : 静的配列';
//バイト配列を初期化して
//String型の文字列をバイト配列にコピー
LByteSize := Length(LText) * SizeOf(Char);
FillChar(LByteArr, SizeOf(LByteArr), 0);
Move(LText[1], LByteArr[0], LByteSize);
//テスト用バイト配列データ作成終了
//バイト配列のデータをChar型の配列にコピー
LByteSize := Length(LByteArr);
FillChar(LCharArrDst, Length(LCharArrDst) * SizeOf(Char), #0);
Move(LByteArr[0], LCharArrDst[0], LByteSize);
//結果の表示
LTextDst := LCharArrDst;
Memo1.Lines.Add(LTextDst);
end;
String 型の文字列からバイト配列を作成する際,TEncoding クラスの GetBytes メソッドが使用できます.その例です.エンコードは Unicode を指定します. |
|
図2
バイト配列のデータを Char 型の文字配列に変換
- TEncoding クラスの GetBytes メソッドを使用してバイト配列のデータを作成する例
|
//=============================================================================
// バイト型配列のデータをChar型の文字配列のデータにする例
//
// テスト用の文字列をバイト型の配列データとして格納
// そのバイト配列データをChar型の文字配列にコピーする
//
// 変換元のバイト配列データをTEncodingの機能を使用して作成する例
//
// TCharArrayはChar型の動的配列
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
LText : string;
LCharArrDst : TCharArray;
LByteArr : TBytes;
LByteSize : Integer;
LTextDst : string;
begin
Memo1.Lines.Clear;
LText := 'バイト配列データを Char 型の文字配列に' + sLineBreak
+ 'バイト配列データ作成に TEncoding を利用';
LByteArr := TEncoding.Unicode.GetBytes(LText.ToCharArray);
//バイト配列のデータをChar型の配列にコピー
LByteSize := Length(LByteArr);
SetLength(LCharArrDst, LByteSize);
Move(LByteArr[0], LCharArrDst[0], LByteSize);
//結果の表示
LTextDst := PChar(@LCharArrDst[0]);
Memo1.Lines.Add(LTextDst);
end;
02_バイト配列のデータと String 型の文字列との変換 |
バイト配列のデータと String 型の文字列との相互変換のサンプルです. |
|
図3
バイト配列のデータと String 型の文字列の変換 |
//=============================================================================
// バイト型配列のデータをString型の文字列にする
//
// テスト用の文字列をバイト型の配列データとして格納
// そのバイト配列データをString型の文字列にコピーする
//
// TBytesはバイト型の動的配列
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
LText : string;
LStringDst : string;
LByteArr : TBytes;
LByteSize : Integer;
begin
Memo1.Lines.Clear;
//テスト用の文字列
LText := 'バイト配列データを String 型の文字列に' + sLineBreak
+ 'バイト配列 : 動的配列';
//バイト配列のサイズを設定して
//String型の文字列をバイト配列にコピー
LByteSize := Length(LText) * SizeOf(Char);
SetLength(LByteArr, LByteSize);
Move(LText[1], LByteArr[0], LByteSize);
//テスト用バイト配列データ作成終了
//バイト配列のデータをString型の文字列のデータにする
//String型の文字列の最初の文字の要素番号は1であることに注意
LByteSize := Length(LByteArr);
SetLength(LStringDst, LByteSize div SizeOf(Char));
Move(LByteArr[0], LStringDst[1], LByteSize);
//結果の表示
Memo1.Lines.Add(LStringDst);
end;
//=============================================================================
// バイト型配列のデータをString型の文字列にする
//
// テスト用の文字列をバイト型の配列データとして格納
// そのバイト配列データをString型の文字列にコピーする
//
// TByteArrayはバイト型の静的配列
//=============================================================================
procedure TForm1.Button2Click(Sender: TObject);
var
LText : string;
LStringDst : string;
LByteArr : TByteArray;
LByteSize : Integer;
begin
Memo1.Lines.Clear;
//テスト用の文字列
LText := 'バイト配列データを String 型の文字列に' + sLineBreak
+ 'バイト配列 : 静的配列';
//バイト配列のサイズを設定して
//String型の文字列をバイト配列にコピー
LByteSize := Length(LText) * SizeOf(Char);
Move(LText[1], LByteArr[0], LByteSize);
//テスト用バイト配列データ作成終了
//バイト配列のデータをString型の文字列のデータにする
//String型の文字列の最初の文字の要素番号は1であることに注意
LByteSize := Length(LByteArr);
SetLength(LStringDst, LByteSize div SizeOf(Char));
Move(LByteArr[0], LStringDst[1], LByteSize);
//結果の表示
Memo1.Lines.Add(LStringDst);
end;
03_バイト配列のデータと PChar 型の文字列との変換 |
Move 関数を使用してバイト配列のデータを PChar 型の文字列に変換するサンプルです. |
|
図4
バイト配列のデータを PChar 型の文字列に変換 |
//=============================================================================
// バイト型配列のデータをPChar型の文字列にする
//
// テスト用の文字列をバイト型の配列データに格納
// そのバイト配列データをPChar型の文字列にコピーする
//
// TBytesはバイト型の動的配列
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
LText : string;
LPCharDst : PChar;
LByteArr : TBytes;
LByteSize : Integer;
begin
Memo1.Lines.Clear;
//テスト用の文字列
LText := 'バイト配列データを PChar 型の文字列に';
//バイト配列のサイズを設定して
//String型の文字列をバイト配列にコピー
LByteSize := Length(LText) * SizeOf(Char);
SetLength(LByteArr, LByteSize);
Move(LText[1], LByteArr[0], LByteSize);
//テスト用バイト配列データ作成終了
//バイト配列のデータをPChar型の文字列のデータにする
//Null文字分のメモリも確保しておく
//AllocMem関数はメモリを0に初期化するので文字でない末尾はNull文字となる
LPCharDst := AllocMem(LByteSize + SizeOf(Char));
try
Move(LByteArr[0], LPCharDst^, LByteSize);
//結果の表示
Memo1.Lines.Add(LPCharDst);
finally
FreeMem(LPCharDst);
end;
end;
上のサンプルとは逆に,Move 関数を使用して PChar 型の文字列のデータをバイト配列のデータとしてコピーするサンプルです. |
|
図5
PChar 型の文字列をバイト配列のデータに変換 |
//=============================================================================
// PChar型の文字列のデータをバイト配列にコピーする
//
// TBytesはバイト型の動的配列
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
LPCharSrc : PChar;
LByteArr : TBytes;
LByteSize : Integer;
begin
Memo1.Lines.Clear;
//テスト用文字列
LPCharSrc := 'PChar 型の文字列をバイト配列データに';
//バイト配列のサイズを設定して
//PChar型の文字列データをバイト配列にコピー
//結果を文字列として取得するにはNull終端文字の分の確保が必要
//PChar型の文字列のNull終端文字もコピーする
LByteSize := (StrLen(LPCharSrc) + 1) * SizeOf(Char);
SetLength(LByteArr, LByteSize);
Move(LPCharSrc^, LByteArr[0], LByteSize);
//結果の表示
Memo1.Lines.Add(PChar(LByteArr));
end;
バイト配列のデータと数値との相互変換のサンプルです.
まず数値を Move 関数を使用して,バイト配列のデータにします.そのバイト配列のデータを Move 関数を使用して別の数値の変数のデータとしてコピーします.
整数型と実数型の数値でテストしています. |
|
図6
バイト配列データと数値との変換
|
|
図7
バイト配列データと数値との変換
|
//=============================================================================
// バイト型配列のデータと数値の変換
//
// テスト用の数値をバイト配列データとして格納
// そのバイト配列のデータをInteger型の数値として取り出す
//
// TBytesはバイト型の動的配列
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
LIntegerSrc : Integer;
LIntegerDst : Integer;
LByteArr : TBytes;
LByteSize : Integer;
begin
Memo1.Lines.Clear;
//テスト用の数値
LIntegerSrc := 123456;
//バイト配列のサイズを設定して数値をバイト配列に格納
LByteSize := SizeOf(Integer);
SetLength(LByteArr, LByteSize);
Move(LIntegerSrc, LByteArr[0], LByteSize);
//バイト配列のデータを数値の変数にコピー
Move(LByteArr[0], LIntegerDst, SizeOf(Integer));
//結果の表示
Memo1.Lines.Add('バイト配列データと整数値の変換');
Memo1.Lines.Add(IntToStr(LIntegerDst));
end;
//=============================================================================
// バイト型配列のデータと数値の変換
//
// テスト用の数値をバイト配列データとして格納
// そのバイト配列のデータをIDouble型の数値として取り出す
//
// TBytesはバイト型の動的配列
//=============================================================================
procedure TForm1.Button2Click(Sender: TObject);
var
LDoubleSrc : Double;
LDoubleDst : Double;
LByteArr : TBytes;
LByteSize : Integer;
begin
Memo1.Lines.Clear;
//テスト用の数値
LDoubleSrc := 1.23456E+12;
//バイト配列のサイズを設定して数値をバイト配列に格納
LByteSize := SizeOf(Double);
SetLength(LByteArr, LByteSize);
Move(LDoubleSrc, LByteArr[0], LByteSize);
//バイト配列のデータを数値の変数にコピー
Move(LByteArr[0], LDoubleDst, SizeOf(Double));
//結果の表示
Memo1.Lines.Add('バイト配列データと実数値の変換');
Memo1.Lines.Add(FormatFloat('0.000E+00', LDoubleDst));
end;
05_読み出しと書き込み位置を指定したバイト配列のコピー |
バイト配列は要素番号 (インデックスの番号) で先頭からのバイト位置を指定できます.Move 関数ではコピーするバイト数が設定できます.このことを利用すると,コピー元のバイト配列の任意の位置から指定バイト数だけをコピー先のバイト配列にコピーできます.その例です.
テスト用のバイトデータとして 1 バイトの文字である AnsiString の ASCII 文字を使用しています.
TMemo にデータを表示する際,string で型キャストしています.これは「W1057 文字列の暗黙のキャスト ('AnsiString' から 'string')」という警告を回避するためです. |
|
図8
バイト配列データを別のバイト配列にコピー
- 'ABCDEFG' はコピー元のバイトデータ
- '123456789' はコピー先のバイトデータ
- 最後の行がコピーした結果のデータ
|
//=============================================================================
// バイト型配列のデータを別のバイト配列にコピー
//
// コピー元のバイト配列の任意の要素から指定バイト数をコピー
// コピー先のバイト配列の任意の位置へコピー(上書き)
//
// TBytesはバイト型の動的配列
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
LByteArrSrc : TBytes;
LByteArrDst : TBytes;
LText : AnsiString;
begin
Memo1.Lines.Clear;
Memo1.Lines.Add('バイト配列のデータを別のバイト配列にコピー');
Memo1.Lines.Add('');
//データをバイト配列に格納して確認表示
LText :='ABCDEFG';
SetLength(LByteArrSrc, Length(LText));
Move(LText[1], LByteArrSrc[0], Length(LText));
Memo1.Lines.Add(string(LText));
//別のデータを別のバイト配列に格納して確認表示
LText :='123456789';
SetLength(LByteArrDst, Length(LText));
Move(LText[1], LByteArrDst[0], Length(LText));
Memo1.Lines.Add(string(LText));
//バイト配列のデータを別のバイト配列にコピー
Move(LByteArrSrc[2], LByteArrDst[3], 4);
//コピー先のバイト配列のデータを文字列に変換
SetLength(LText, Length(LByteArrDst));
Move(LByteArrDst[0], LText[1], Length(LByteArrDst));
//その文字列を結果として表示
Memo1.Lines.Add('');
Memo1.Lines.Add(string(LText));
end;
|