Delphi Programming / Object Pascal
サイトのトップページへ リンクのページへ ロゴマーク
[掲載 2008年10月22日] [更新 2014年04月14日] Delphi サンプルプログラム集
   
885_Windows API の関数を使用した文字コードの変換
動作確認等 Windows 7 U64(SP1) + Delphi 2007-R2 Pro, Delphi XE Pro
885_MojiCodeWin32API.zip [1,345 KB] 2014年04月14日版(EXE同梱)



  • 2014年04月14日
  • Delphi 2009 以降用のサンプルを追加




Windows API の関数を使用した文字コードの変換


Windows API の文字列変換用関数,MultiByteToWideChar と WideCharToMultiByte を使用した文字のコードページ変換サンプルです.
本ページのサンプルでは.ディスク上の JIS コードのテキストファイルを,Shift-JIS コードと UTF-8N のテキストに変換します.
  • MultiByteToWideChar でユニコードに変換
  • WideCharToMultiByte で目的の文字コードに変換
という手順で処理します.大きいサイズのテキストファイルも比較的高速に変換できます.コードページの指定を変更すれば,Shift-JIS から JIS への変換も可能です.


JIS コードページは,50220, 50221, 50222 の 3 つありますが,本ページのサンプルで使用するテキストファイルのコードページを,Mlang の機能を使用して調べたところ,50220 となっていました.そこで,この 50220 を使用しています.
他のコードページの文字から変換するには,この元の文字のコードページを変更します.


図1
JIS コードページは 50220, 50221, 50222 の 3 つ
図2
テスト用のファイルのテキストは 50220




01_JIS 文字コードからShift-JIS 等への変換 - Delphi 2007 以前用


非ユニコード版,つまり Ansi 版の Delphi 用のサンプルです.
Delphi 2007 以前で使用可能です.


図3
実行画面

図4
テスト用の JIS コードのテキストファイル


図5
変換結果のファイル

リスト1
JIS 文字コードから Shift-JIS 等への変換 - Delphi 2007 以前用
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Buttons, ExtCtrls;

type
  TForm1 = class(TForm)
    OpenDialog1: TOpenDialog;
    Button1: TButton;
    SpeedButton1: TSpeedButton;
    SpeedButton2: TSpeedButton;
    SpeedButton3: TSpeedButton;
    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);
  private
    { Private 宣言 }
    ReadFileName : String;
    SaveFileName : String;
    SLRead : TStringList;
    SLSave : TStringList;
    function Convertfunction(SrcCode, DestCode: Integer;
      SrcString: String): String;
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

//=============================================================================
//  文字列格納用のStringListを生成
//
//  SLRead 変換前の文字列を格納するTStringList
//  SLSave 変換後の文字列を格納するTStringList
//=============================================================================
procedure TForm1.FormShow(Sender: TObject);
begin
  Button1.Enabled      := True;
  SpeedButton1.Enabled := False;
  SpeedButton2.Enabled := False;
  SpeedButton3.Enabled := False;

  SLRead := TStringList.Create;
  SLSave := TStringList.Create;
end;

//=============================================================================
//  使用したTSrgintList破棄
//=============================================================================
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  FreeAndNil(SLRead);
  FreeAndNil(SLSave);
end;

//=============================================================================
//  OpenDialog1でテキストファイルを選択し
//  変換元のテキストをTStringListに読込む
//  変換元のテキストファイルは,このアプリのフォルダの下のBeforeFileフォルダ
//  保存先は同様にすぐ下のChangedFileフォルダ
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
begin
  OpenDialog1.InitialDir := ExpandFileName('../BeforeFile');

  if OpenDialog1.Execute then begin
    ReadFileName := OpenDialog1.FileName;
    SLRead.Clear;
    SLRead.LoadFromFile(ReadFileName);

    SpeedButton1.Enabled := True;
    SpeedButton2.Enabled := True;
    SpeedButton3.Enabled := True;
  end;
end;

//=============================================================================
//  JISからJISへの変換
//=============================================================================
procedure TForm1.SpeedButton1Click(Sender: TObject);
begin
  //保存ファイル名を作成
  //読出したファイル名の後ろに_to_JISを付加
  SaveFileName := ExpandFileName('../ChangedFile') + PathDelim
                  + ChangeFileExt(ExtractFileName(ReadFileName), '')
                  + '_to_JIS.txt';

  Screen.Cursor := crHourGlass;
  try
    SLSave.Text := Convertfunction(50220, 50220, SLRead.Text);
    SLSave.SaveToFile(SaveFileName);
  finally
    Screen.Cursor := crDefault;
  end;
end;

//=============================================================================
//  JISからShit-JISへの変換
//=============================================================================
procedure TForm1.SpeedButton2Click(Sender: TObject);
begin
  //保存ファイル名を作成
  //読出したファイル名の後ろに_to_S-JISを付加
  SaveFileName := ExpandFileName('../ChangedFile') + PathDelim
                  + ChangeFileExt(ExtractFileName(ReadFileName), '')
                  + '_to_S-JIS.txt';

  Screen.Cursor := crHourGlass;
  try
    SLSave.Text := Convertfunction(50220, 932, SLRead.Text);
    SLSave.SaveToFile(SaveFileName);
  finally
    Screen.Cursor := crDefault;
  end;
end;

//=============================================================================
//  JISからUTF-8Nへの変換
//=============================================================================
procedure TForm1.SpeedButton3Click(Sender: TObject);
begin
  //保存ファイル名を作成
  //読出したファイル名の後ろに_to_UTF-8Nを付加
  SaveFileName := ExpandFileName('../ChangedFile') + PathDelim
                  + ChangeFileExt(ExtractFileName(ReadFileName), '')
                  + '_to_UTF-8N.txt';

  Screen.Cursor := crHourGlass;
  try
    SLSave.Text := Convertfunction(50220, 65001, SLRead.Text);
    SLSave.SaveToFile(SaveFileName);
  finally
    Screen.Cursor := crDefault;
  end;
end;

//=============================================================================
//  文字コード変換関数
//
//  MultiByteToWideCharでユニコード文字セットに変換
//  WideCharToMultiByteでユニコード文字から目的のマルチバイト文字列に変換
//
//  [引数]
//  SrcCode    : 変換元の文字コードを指定
//  DestCode   : 変換後の文字コードを指定
//  SrcString  : 変換元のテキストを格納した文字列
//  関数の戻り値が変換後の文字列
//=============================================================================
function TForm1.Convertfunction(SrcCode, DestCode: Integer;
  SrcString: String): String
  ;
var
  DestLen : Integer;
  wStr    : WideString;
begin
  //変換後の長さを取得して0を超えれば変換
  DestLen := MultiByteToWideChar(SrcCode, 0, PChar(SrcString), -1, nil, 0);

  if DestLen > 0 then begin
    SetLength(wStr, DestLen);
    MultiByteToWideChar(
      SrcCode, 0, PChar(SrcString), -1, PWideChar(wStr), DestLen);

    //変換後の長さを取得して0を超えていれば変換
    DestLen := WideCharToMultiByte(
                 DestCode, 0, PWideChar(wStr), -1, nil, 0, nil, nil);

    if DestLen > 0 then begin
      SetLength(Result, DestLen);
      WideCharToMultiByte(
        DestCode, 0, PWideChar(wStr), -1, PChar(Result), DestLen, nil, nil);
    end;
  end;
end;

end.




02_JIS 文字コードから Shift-JIS 等への変換 - Delphi 2009 以降用


ユニコード版の Delphi,つまり Delphi 2009 以降用のサンプルです.
Delphi 2009 以降では,MultiByteToWideChar 関数でユニコードに変換してしまえば,後は,コードページ変換用の関数類を使用して文字のコードページの変換ができます.

TEncoding.GetEncoding 関数を使用した場合は,TEncoding の解放が必要です.本サンプルコードのように,TEncoding の変数を定義して,使用しなくなったら Free するのが確実でしょう.



図6
実行画面


リスト2
JIS 文字コードから Shift-JIS 等への変換 - Delphi 2009 以降用
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Buttons;

type
  TForm1 = class(TForm)
    OpenDialog1: TOpenDialog;
    Button1: TButton;
    SpeedButton1: TSpeedButton;
    SpeedButton2: TSpeedButton;
    SpeedButton3: TSpeedButton;
    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);
  private
    { Private 宣言 }
    ReadFileName : String;
    SaveFileName : String;
    SLRead : TStringList;
    SLSave : TStringList;
    function ConvertToUTF16(SrcCode: Integer; SrcString: RawByteString): String;
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

//=============================================================================
//  文字列格納用のStringListを生成
//
//  SLRead 変換前の文字列を格納するTStringList
//  SLSave 変換後の文字列を格納するTStringList
//=============================================================================
procedure TForm1.FormShow(Sender: TObject);
begin
  Button1.Enabled      := True;
  SpeedButton1.Enabled := False;
  SpeedButton2.Enabled := False;
  SpeedButton3.Enabled := False;

  SLRead := TStringList.Create;
  SLSave := TStringList.Create;
end;

//=============================================================================
//  使用したTSrgintList破棄
//=============================================================================
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  FreeAndNil(SLRead);
  FreeAndNil(SLSave);
end;

//=============================================================================
//  OpenDialog1でテキストファイルを選択し
//  変換元のテキストをTStringListに読込む
//  変換元のテキストファイルは,このアプリのフォルダの下のBeforeFileフォルダ
//  保存先は同様にすぐ下のChangedFileフォルダ
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
begin
  OpenDialog1.InitialDir := ExpandFileName('../BeforeFile');

  if OpenDialog1.Execute then begin
    ReadFileName := OpenDialog1.FileName;
    SLRead.Clear;
    SLRead.LoadFromFile(ReadFileName);

    SpeedButton1.Enabled := True;
    SpeedButton2.Enabled := True;
    SpeedButton3.Enabled := True;
  end;
end;

//=============================================================================
//  JISからJISへの変換
//=============================================================================
procedure TForm1.SpeedButton1Click(Sender: TObject);
var
  Enc : TEncoding;
begin
  //保存ファイル名を作成
  //読出したファイル名の後ろに_to_JISを付加
  SaveFileName := ExpandFileName('../ChangedFile') + PathDelim
                  + ChangeFileExt(ExtractFileName(ReadFileName), '')
                  + '_to_JIS.txt';

  Screen.Cursor := crHourGlass;
  Enc := TEncoding.GetEncoding(50221);
  try
    SLSave.Text := ConvertToUTF16(50220, RawByteString(SLRead.Text));
    SLSave.SaveToFile(SaveFileName, Enc);
  finally
    Screen.Cursor := crDefault;
    Enc.Free;
  end;
end;

//=============================================================================
//  JISからShit-JISへの変換
//=============================================================================
procedure TForm1.SpeedButton2Click(Sender: TObject);
var
  Enc : TEncoding;
begin
  //保存ファイル名を作成
  //読出したファイル名の後ろに_to_S-JISを付加
  SaveFileName := ExpandFileName('../ChangedFile') + PathDelim
                  + ChangeFileExt(ExtractFileName(ReadFileName), '')
                  + '_to_S-JIS.txt';

  Screen.Cursor := crHourGlass;
  Enc := TEncoding.GetEncoding(932);
  try
    SLSave.Text := ConvertToUTF16(50220, RawByteString(SLRead.Text));
    SLSave.SaveToFile(SaveFileName, Enc);
  finally
    Screen.Cursor := crDefault;
    Enc.Free;
  end;
end;

//=============================================================================
//  JISからUTF-8Nへの変換
//=============================================================================
procedure TForm1.SpeedButton3Click(Sender: TObject);
begin
  //保存ファイル名を作成
  //読出したファイル名の後ろに_to_UTF-8Nを付加
  SaveFileName := ExpandFileName('../ChangedFile') + PathDelim
                  + ChangeFileExt(ExtractFileName(ReadFileName), '')
                  + '_to_UTF-8N.txt';

  Screen.Cursor := crHourGlass;
  try
    SLSave.Text := ConvertToUTF16(50220, RawByteString(SLRead.Text));
    SLSave.SaveToFile(SaveFileName, TEncoding.UTF8);
  finally
    Screen.Cursor := crDefault;
  end;
end;

//=============================================================================
//  文字コード変換関数
//  MultiByteToWideCharでユニコード文字セットに変換
//
//  [引数]
//  SrcCode    : 変換元の文字コードを指定
//  SrcString  : 変換元のテキストを格納した文字列
//  関数の戻り値が変換後の文字列
//=============================================================================
function TForm1.ConvertToUTF16(SrcCode: Integer; SrcString: RawByteString): String;
var
  DestLen : Integer;
  dwFlags : DWORD;
begin
  Result := '';

  dwFlags := 0;
  if SrcCode = 932 then dwFlags := MB_PRECOMPOSED;

  //変換後の長さを取得して0を超えれば変換
  DestLen := MultiByteToWideChar(
               SrcCode, dwFlags, PAnsiChar(SrcString), -1, nil, 0);

  if DestLen > 0 then begin
    SetLength(Result, DestLen);
    MultiByteToWideChar(
      SrcCode, dwFlags, PAnsiChar(SrcString), -1, PWideChar(Result), DestLen);
  end;
end;

end.




03_Delphi 2009 以降の TEncoding クラスだけを使用した方法


これも,ユニコード版の Delphi,つまり Delphi 2009 以降用のサンプルです.
上のサンプルでも Delphi 2009 で実装された TEncoding クラスを使用していますが,TEncoding クラスを使用すれば,わざわざ MultiByteToWideChar 関数を使用する必要はありません.

TEncoding.GetEncoding 関数を使用した場合は,TEncoding の解放が必要です.本サンプルコードのように,TEncoding の変数を定義して,使用しなくなったら Free するのが確実でしょう.



図7
実行画面


リスト3
JIS コードからの変換.Delphi 2009 以降の TEncoding クラスだけを使用した方法
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Buttons;

type
  TForm1 = class(TForm)
    SpeedButton1: TSpeedButton;
    SpeedButton2: TSpeedButton;
    SpeedButton3: TSpeedButton;
    procedure SpeedButton1Click(Sender: TObject);
    procedure SpeedButton2Click(Sender: TObject);
    procedure SpeedButton3Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

//=============================================================================
//  JISからJISへの変換
//=============================================================================
procedure TForm1.SpeedButton1Click(Sender: TObject);
var
  ReadFileName : String;
  SaveFileName : String;
  SLRead  : TStringList;
  EncRead : TEncoding;
  EncSave : TEncoding;
begin
  ReadFileName := ExpandFileName('../BeforeFile') + PathDelim + 'JIS.txt';
  //保存ファイル名を作成
  //読出したファイル名の後ろに_to_JISを付加
  SaveFileName := ExpandFileName('../ChangedFile') + PathDelim
                  + ChangeFileExt(ExtractFileName(ReadFileName), '')
                  + '_to_JIS.txt';

  Screen.Cursor := crHourGlass;

  SLRead  := TStringList.Create;
  EncRead := TEncoding.GetEncoding(50220);
  EncSave := TEncoding.GetEncoding(50221);
  try
    SLRead.LoadFromFile(ReadFileName, EncRead);
    SLRead.SaveToFile(SaveFileName, EncSave);
  finally
    SLRead.Free;
    EncRead.Free;
    EncSave.Free;
    Screen.Cursor := crDefault;
  end;
end;

//=============================================================================
//  JISからShit-JISへの変換
//=============================================================================
procedure TForm1.SpeedButton2Click(Sender: TObject);
var
  ReadFileName : String;
  SaveFileName : String;
  SLRead  : TStringList;
  EncRead : TEncoding;
  EncSave : TEncoding;
begin
  ReadFileName := ExpandFileName('../BeforeFile') + PathDelim + 'JIS.txt';
  //保存ファイル名を作成
  //読出したファイル名の後ろに_to_S-JISを付加
  SaveFileName := ExpandFileName('../ChangedFile') + PathDelim
                  + ChangeFileExt(ExtractFileName(ReadFileName), '')
                  + '_to_S-JIS.txt';

  Screen.Cursor := crHourGlass;

  SLRead  := TStringList.Create;
  EncRead := TEncoding.GetEncoding(50220);
  EncSave := TEncoding.GetEncoding(932);
  try
    SLRead.LoadFromFile(ReadFileName, EncRead);
    SLRead.SaveToFile(SaveFileName, EncSave);
  finally
    SLRead.Free;
    EncRead.Free;
    EncSave.Free;
    Screen.Cursor := crDefault;
  end;
end;

//=============================================================================
//  JISからUTF-8への変換
//=============================================================================
procedure TForm1.SpeedButton3Click(Sender: TObject);
var
  ReadFileName : String;
  SaveFileName : String;
  SLRead  : TStringList;
  EncRead : TEncoding;
begin
  ReadFileName := ExpandFileName('../BeforeFile') + PathDelim + 'JIS.txt';
  //保存ファイル名を作成
  //読出したファイル名の後ろに_to_UTF-8.txtを付加
  SaveFileName := ExpandFileName('../ChangedFile') + PathDelim
                  + ChangeFileExt(ExtractFileName(ReadFileName), '')
                  + '_to_UTF-8.txt';

  Screen.Cursor := crHourGlass;

  SLRead  := TStringList.Create;
  EncRead := TEncoding.GetEncoding(50220);
  try
    SLRead.LoadFromFile(ReadFileName, EncRead);
    SLRead.SaveToFile(SaveFileName, TEncoding.UTF8);
  finally
    SLRead.Free;
    EncRead.Free;
    Screen.Cursor := crDefault;
  end;
end;

end.