Delphi Programming / Object Pascal
[掲載 2008年12月13日] [更新 2014年04月16日] Delphi サンプルプログラム集 |
887_ADODBStream を使用した文字コードの変換 |
動作確認等 |
Windows 7 U64(SP1) + Delphi XE Pro |
|
887_ADODBStream.zip [2,293 KB] 2014年04月16日版 (EXE 同梱) |
- 2014年04月16日
- Windows 7 U64(SP1) + Delphi XE Pro で動作確認
- キャンセル機能付きのサンプルは,TMemo にテキストを描画する速度と大差ないので削除
- ADODBStream の生成を,ADOInt ユニットを使用する方法に変更
|
ADODB.Stream を使用した文字コードの変換 |
Microsoft Data Access Components(MDAC) が提供しているオブジェクトに ADO があります.
この ADO の ADODB.Stream を使用した文字コードの変換のサンプルです.ADODB.Stream を使用するには,uses に ADOInt を追加します.
MDAC は,Windows Vista では OS の一部として提供されるようになり,単独のインストールはできなくなっているようです.機能的には Ver2.8 相当のようです.
なお,このページのサンプルコードでは,Big-Endian への変換はできません.
|
Delphi 2009 以降では,テキストファイルの保存の時に TEncoding を使用して,コードページを指定することができます.また,以下のリンクの記事のように,指定コードページ (文字コード) の文字列型を定義して文字列を処理てきるようになり,文字コードの変換が簡単にできます.
本ページのようなサンプルコードを利用する必要性はほとんどないでしょう. |
01_ADODB.Stream で使用可能な 文字コード ( コードページ ) 一覧 |
ADODB.Stream では,文字のコードページではなく,Charset の文字列を使用します.この Charset の一覧は,レジストリの次の場所にあります. |
HKEY_CLASSES_ROOT\MIME\Database\Charset
本サンプルは,レジストリからこれらの値を取得して,各々のキーの内容を表示します.
また,各々 Charset に相当する言語名があれば,それを MLang の機能を使用して取得します. |
- 図1
- ADODB.Stream で使用可能な文字セットがある場所
|
|
下図は実行結果です.上の TListBox の項目をクリックすると,その Charset の文字コードセット名等を,下の TMemo に表示します. |
|
図2
設計時画面
|
|
図3
一覧表示
- 上が Charset の一覧
- 下は各 Charset のキー名とその値
- 空欄は定義されていないもの
- 言語名は Mlang から取得した値
|
リスト1
ADODB.Stream で使用可能な Charset の一覧 |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Buttons, ExtCtrls, Registry;
type
TForm1 = class(TForm)
Panel2: TPanel;
Button1: TButton;
ListBox1: TListBox;
Memo1: TMemo;
procedure Button1Click(Sender: TObject);
procedure ListBox1Click(Sender: TObject);
private
{ Private 宣言 }
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
uses MultiLanguage_TLB;
{$R *.dfm}
//=============================================================================
// ADODB.StreamのCharsetプロパティで使用可能なCharset名をリスト
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
Registry : TRegistry;
RegKey : String;
slCharsetList : TStringList;
begin
slCharsetList := TStringList.Create;
slCharsetList.Clear;
slCharsetList.Sorted := True;
//レジストリから文字コードの情報を取得してリストに格納
Registry := TRegistry.Create(KEY_READ);
try
Registry.RootKey := HKEY_CLASSES_ROOT;
RegKey := '\mime\database\Charset\';
Registry.OpenKey(RegKey, False);
Registry.GetKeyNames(slCharsetList);
Registry.CloseKey;
Listbox1.Items.Assign(slCharsetList);
finally
Registry.Free;
FreeAndNil(slCharsetList);
end;
end;
//=============================================================================
// Listbox1で選択したCharssetのレジストリ内の情報を取得して表示
// MLangの機能を使用して言語名も取得
//
// 以下のキーがあるが,定義されていないものもある
// CodePage
// InternetEncoding
// AliasForCharset
//=============================================================================
procedure TForm1.ListBox1Click(Sender: TObject);
var
Registry : TRegistry;
RegKey : String;
AIndex : Integer;
TempStr : String;
CodePage : Integer;
IECodePage : Integer;
MLang : IMultiLanguage;
MIMECPInfo : TMIMECPINFO;
strLocale : String;
begin
AIndex := ListBox1.ItemIndex;
if AIndex<0 then exit;
Memo1.Lines.Clear;
Memo1.Lines.Add('Charset : ' + ListBox1.Items[ListBox1.ItemIndex]);
RegKey := '\mime\database\Charset\';
Registry := TRegistry.Create(KEY_READ);
try
Registry.RootKey := HKEY_CLASSES_ROOT;
try
Registry.OpenKey(RegKey+ ListBox1.Items[AIndex], False);
CodePage := Registry.ReadInteger('CodePage');
Memo1.Lines.Add('CodePage : ' + IntToStr(CodePage));
except
Memo1.Lines.Add('CodePage : ');
end;
IECodePage := -1;
try
Registry.OpenKey(RegKey+ ListBox1.Items[AIndex], False);
IECodePage := Registry.ReadInteger('InternetEncoding');
Memo1.Lines.Add('InternetEncoding : ' + IntToStr(IECodePage));
except
Memo1.Lines.Add('InternetEncoding : ');
end;
try
Registry.OpenKey(RegKey+ ListBox1.Items[AIndex], False);
TempStr := Registry.ReadString('AliasForCharset');
Memo1.Lines.Add('AliasForCharset : ' + TempStr);
except
Memo1.Lines.Add('AliasForCharset : ');
end;
Registry.CloseKey;
//言語名があれば取得
//InternetEncodingの値から取得
if IECodePage >= 0 then begin
//mlangのオブジェクトを生成
MLang := CoCMultiLanguage.Create;
try
MLang.GetCodePageInfo(IECodePage, MIMECPInfo);
strLocale := MIMECPInfo.wszDescription;
finally
MLang := nil;
end;
end;
Memo1.Lines.Add('Locale : ' + strLocale);
finally
Registry.Free;
end;
end;
end.
02_ADODB.Stream を使用した文字コード変換サンプル |
文字コード変換のテストプログラムです.添付のテキストファイル専用のコードとなっています.
変換元の文字コードが既知の場合の参考です.ファイルからテキストを読み出す時に,そのテキストの文字コードを指定して読み出します.保存の時も,変換後の文字コードを指定して保存します. |
|
図4
設計時画面 |
|
図5
実行
- [Read File] ボタンをクリックしてファイルを選択
- [Read File]ボタンの下の表示は読出した文字コード
|
|
図6
添付のテスト用テキストファイル
|
リスト2
ADODB.Stream を使用した文字コード変換のテスト |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Buttons, ExtCtrls, ADOInt;
type
TForm1 = class(TForm)
OpenDialog1: TOpenDialog;
Button1: TButton;
SpeedButton1: TSpeedButton;
SpeedButton2: TSpeedButton;
SpeedButton3: TSpeedButton;
SpeedButton5: TSpeedButton;
SpeedButton6: TSpeedButton;
Panel1: TPanel;
procedure FormShow(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure Button1Click(Sender: TObject);
procedure SpeedButton1Click(Sender: TObject);
procedure SpeedButton2Click(Sender: TObject);
procedure SpeedButton3Click(Sender: TObject);
procedure SpeedButton5Click(Sender: TObject);
procedure SpeedButton6Click(Sender: TObject);
private
{ Private 宣言 }
ADOReadStream : ADOInt._Stream;
ReadFileName : String;
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
uses ActiveX;
{$R *.dfm}
//=============================================================================
// ADODB.Streamオブジェクトを生成して開く
// ADOReadStream : テキストファイルから読出した内容を保持
//=============================================================================
procedure TForm1.FormShow(Sender: TObject);
begin
//変換元のテキストを読込むADOBD.Streamを生成して開く
ADOReadStream := CoStream.Create;
ADOReadStream.Open(EmptyParam, 0, adOpenStreamUnspecified, '', '');
SpeedButton1.Enabled := False;
SpeedButton2.Enabled := False;
SpeedButton3.Enabled := False;
SpeedButton5.Enabled := False;
SpeedButton6.Enabled := False;
end;
//=============================================================================
// 使用したStreamオブジェクトを閉じて無効に
//=============================================================================
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
ADOReadStream.Close;
ADOReadStream := nil;
end;
//=============================================================================
// OpenDialog1でテキストファイルを選択し
// 変換元のテキストをStreamオブジェクトに(ADOReadStream)に読込む
// 変換元のテキストファイルは,BeforeFileフォルダ
// 変換後のテキストファイルの保存先はChangedFileフォルダ
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
AFileName : String;
begin
OpenDialog1.InitialDir := ExpandFileName('../BeforeFile');
if OpenDialog1.Execute then begin
Update;
Panel1.Caption := '';
ReadFileName := OpenDialog1.FileName;
//テストなのでファイル名に応じた変換元文字コードをセット
AFileName := ExtractFileName(ReadFileName);
if AFileName = 'EUC.txt' then Panel1.Caption := 'euc-jp';
if AFileName = 'JIS.txt' then Panel1.Caption := 'iso-2022-jp';
if AFileName = 'S-JIS.txt' then Panel1.Caption := 'shift_jis';
if AFileName = 'UNI-BE.txt' then Panel1.Caption := 'unicodeFFFE';
if AFileName = 'UNI-LE.txt' then Panel1.Caption := 'unicode';
if AFileName = 'UTF-8.txt' then Panel1.Caption := 'utf-8';
if Panel1.Caption = '' then begin
Application.MessageBox('添付のファイル専用のテストです', '結果');
end else begin
//Streamオブジェクトは読みこむ前に文字コードを設定し読込み位置を0に
ADOReadStream.Position := 0;
ADOReadStream.Charset := Panel1.Caption;
ADOReadStream.LoadFromFile(ReadFileName);
SpeedButton1.Enabled := True;
SpeedButton2.Enabled := True;
SpeedButton3.Enabled := True;
SpeedButton5.Enabled := True;
SpeedButton6.Enabled := True;
end;
end;
end;
//=============================================================================
// ECUへの変換
//=============================================================================
procedure TForm1.SpeedButton1Click(Sender: TObject);
var
ADOSaveStream : ADOInt._Stream;
SaveFileName : String;
begin
//保存ファイル名を作成
//読出したファイル名の後ろに_to_ECUを付加
SaveFileName := ExpandFileName('../ChangedFile') + PathDelim
+ ChangeFileExt(ExtractFileName(ReadFileName), '')
+ '_to_ECU.txt';
Screen.Cursor := crHourGlass;
//変換先のADODB.Streamを生成して開く
ADOSaveStream := CoStream.Create;
try
ADOSaveStream.Open(EmptyParam, adModeUnknown, adOpenStreamUnspecified, '', '');
//変換後のテキストを入れるStreamオブジェクトの設定
//位置を0にして文字コードを設定
ADOSaveStream.Position := 0;
ADOSaveStream.Charset := 'euc-jp';
//変換元の読出し位置を0にする
ADOReadStream.Position := 0;
//CopyToメソッドを実行すると,出力先のStreamに変換された文字が格納される
ADOReadStream.CopyTo(ADOSaveStream, -1);
//保存する
ADOSaveStream.SaveToFile(SaveFileName, adSaveCreateOverWrite);
finally
ADOSaveStream.Close;
ADOSaveStream := nil;
Screen.Cursor := crDefault;
end;
end;
//=============================================================================
// JISへの変換
//=============================================================================
procedure TForm1.SpeedButton2Click(Sender: TObject);
var
ADOSaveStream : ADOInt._Stream;
SaveFileName : String;
begin
//保存ファイル名を作成
//読出したファイル名の後ろに_to_ECUを付加
SaveFileName := ExpandFileName('../ChangedFile') + PathDelim
+ ChangeFileExt(ExtractFileName(ReadFileName), '')
+ '_to_JIS.txt';
Screen.Cursor := crHourGlass;
//変換先のADODB.Streamを生成して開く
ADOSaveStream := CoStream.Create;
try
ADOSaveStream.Open(EmptyParam, adModeUnknown, adOpenStreamUnspecified, '', '');
//変換後のテキストを入れるStreamオブジェクトの設定
//位置を0にして文字コードを設定
ADOSaveStream.Position := 0;
ADOSaveStream.Charset := 'iso-2022-jp';
//変換元の読出し位置を0にする
ADOReadStream.Position := 0;
//CopyToメソッドを実行すると,出力先のStreamに変換された文字が格納される
ADOReadStream.CopyTo(ADOSaveStream, -1);
//保存する
ADOSaveStream.SaveToFile(SaveFileName, adSaveCreateOverWrite);
finally
ADOSaveStream.Close;
ADOSaveStream := nil;
Screen.Cursor := crDefault;
end;
end;
//=============================================================================
// Shit-JISへの変換
//=============================================================================
procedure TForm1.SpeedButton3Click(Sender: TObject);
var
ADOSaveStream : ADOInt._Stream;
SaveFileName : String;
begin
//保存ファイル名を作成
//読出したファイル名の後ろに_to_ECUを付加
SaveFileName := ExpandFileName('../ChangedFile') + PathDelim
+ ChangeFileExt(ExtractFileName(ReadFileName), '')
+ '_to_S-JIS.txt';
Screen.Cursor := crHourGlass;
//変換先のADODB.Streamを生成して開く
ADOSaveStream := CoStream.Create;
try
ADOSaveStream.Open(EmptyParam, adModeUnknown, adOpenStreamUnspecified, '', '');
//変換後のテキストを入れるStreamオブジェクトの設定
//位置を0にして文字コードを設定
ADOSaveStream.Position := 0;
ADOSaveStream.Charset := 'shift_jis';
//変換元の読出し位置を0にする
ADOReadStream.Position := 0;
//CopyToメソッドを実行すると,出力先のStreamに変換された文字が格納される
ADOReadStream.CopyTo(ADOSaveStream, -1);
//保存する
ADOSaveStream.SaveToFile(SaveFileName, adSaveCreateOverWrite);
finally
ADOSaveStream.Close;
ADOSaveStream := nil;
Screen.Cursor := crDefault;
end;
end;
//=============================================================================
// UTF-16 Unicode(Little-Endian)への変換
//=============================================================================
procedure TForm1.SpeedButton5Click(Sender: TObject);
var
ADOSaveStream : ADOInt._Stream;
SaveFileName : String;
begin
//保存ファイル名を作成
//読出したファイル名の後ろに_to_ECUを付加
SaveFileName := ExpandFileName('../ChangedFile') + PathDelim
+ ChangeFileExt(ExtractFileName(ReadFileName), '')
+ '_to_UNI-LE.txt';
Screen.Cursor := crHourGlass;
//変換先のADODB.Streamを生成して開く
ADOSaveStream := CoStream.Create;
try
ADOSaveStream.Open(EmptyParam, adModeUnknown, adOpenStreamUnspecified, '', '');
//変換後のテキストを入れるStreamオブジェクトの設定
//位置を0にして文字コードを設定
ADOSaveStream.Position := 0;
ADOSaveStream.Charset := 'unicode';
//変換元の読出し位置を0にする
ADOReadStream.Position := 0;
//CopyToメソッドを実行すると,出力先のStreamに変換された文字が格納される
ADOReadStream.CopyTo(ADOSaveStream, -1);
//保存する
ADOSaveStream.SaveToFile(SaveFileName, adSaveCreateOverWrite);
finally
ADOSaveStream.Close;
ADOSaveStream := nil;
Screen.Cursor := crDefault;
end;
end;
//=============================================================================
// UTF-8への変換
//=============================================================================
procedure TForm1.SpeedButton6Click(Sender: TObject);
var
ADOSaveStream : ADOInt._Stream;
SaveFileName : String;
begin
//保存ファイル名を作成
//読出したファイル名の後ろに_to_ECUを付加
SaveFileName := ExpandFileName('../ChangedFile') + PathDelim
+ ChangeFileExt(ExtractFileName(ReadFileName), '')
+ '_to_UTF-8.txt';
Screen.Cursor := crHourGlass;
//変換先のADODB.Streamを生成して開く
ADOSaveStream := CoStream.Create;
try
ADOSaveStream.Open(EmptyParam, adModeUnknown, adOpenStreamUnspecified, '', '');
//変換後のテキストを入れるStreamオブジェクトの設定
//位置を0にして文字コードを設定
ADOSaveStream.Position := 0;
ADOSaveStream.Charset := 'utf-8';
//変換元の読出し位置を0にする
ADOReadStream.Position := 0;
//CopyToメソッドを実行すると,出力先のStreamに変換された文字が格納される
ADOReadStream.CopyTo(ADOSaveStream, -1);
//保存する
ADOSaveStream.SaveToFile(SaveFileName, adSaveCreateOverWrite);
finally
ADOSaveStream.Close;
ADOSaveStream := nil;
Screen.Cursor := crDefault;
end;
end;
end.
読み出すテキストの文字コードを自動判定するテストです.
Charset に _autodetect または _asutodetect_all を指定して読み出します.保存は上のサンプルと全く同じです.
文字のコードページの判定は,テキスト内の「文字コード」を判定していくことになりますが,調査する文字数が多いほど確実になります.おそらく _all というのは,全ての文字を調べ上げるのではないかと思われます. |
|
図7
設計時画面
|
|
図8
実行
- [Read File] ボタンをクリックしてファイルを選択
|
リスト3
文字コードの自動判定による文字コード変換
このコード以外は,上のサンプルと全く同じ |
//=============================================================================
// OpenDialog1でテキストファイルを選択し
// 変換元のテキストをStreamオブジェクトに(ADOReadStream)に読込む
// 変換元のテキストファイルは,BeforeFileフォルダ
// 変換後のテキストファイルの保存先はChangedFileフォルダ
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
begin
OpenDialog1.InitialDir := ExpandFileName('../BeforeFile');
if OpenDialog1.Execute then begin
Update;
ReadFileName := OpenDialog1.FileName;
//Streamオブジェクトは読みこむ前に文字コードを設定し読込み位置を0に
ADOReadStream.Position := 0;
if CheckBox1.Checked then begin
ADOReadStream.Charset := '_autodetect_all';
end else begin
ADOReadStream.Charset := '_autodetect';
end;
ADOReadStream.LoadFromFile(ReadFileName);
SpeedButton1.Enabled := True;
SpeedButton2.Enabled := True;
SpeedButton3.Enabled := True;
SpeedButton5.Enabled := True;
SpeedButton6.Enabled := True;
end;
end;
04_任意の文字コードのテキストをコントロールに表示 |
コントロールに,読み出したテキストを表示する例です.実際には,コントロールの Text プロパティに等に代入する際に,そのコントロールの文字コードに変換されることになります. |
|
図9
設計時画面
|
|
図10
添付のテキストファイルを表示 |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Buttons, ExtCtrls, ADOInt, ActiveX;
type
TForm1 = class(TForm)
OpenDialog1: TOpenDialog;
Panel1: TPanel;
Button1: TButton;
Memo1: TMemo;
CheckBox1: TCheckBox;
procedure Button1Click(Sender: TObject);
private
{ Private 宣言 }
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
//=============================================================================
// ADODB.Stremを利用した文字コードの変換サンプル
// 直接コントロールに読み込む場合
//
// OpenDialog1でテキストファイルを選択し
// 読み込むテキストファイルはBeforeFileフォルダ
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
ADOReadStream : ADOInt._Stream;
ReadFileName : String;
begin
Memo1.Lines.BeginUpdate;
Memo1.Lines.Clear;
OpenDialog1.InitialDir := ExpandFileName('../BeforeFile');
if OpenDialog1.Execute then begin
Update;
Screen.Cursor := crHourGlass;
ReadFileName := OpenDialog1.FileName;
//変換元のADOBD.Streamを生成して開く
ADOReadStream := CoStream.Create;
try
ADOReadStream.Open(EmptyParam, 0, adOpenStreamUnspecified, '', '');
//文字コード指定
if CheckBox1.Checked then begin
ADOReadStream.Charset := '_autodetect_all';
end else begin
ADOReadStream.Charset := '_autodetect';
end;
//ファイルから読出す
ADOReadStream.LoadFromFile(ReadFileName);
//Memo1に表示(Memo1の文字コードに変換される)
Memo1.Text := ADOReadStream.ReadText(-1);
finally
ADOReadStream.Close;
ADOReadStream := nil;
Screen.Cursor := crDefault;
end;
end;
Memo1.Lines.EndUpdate;
end;
end.
|