2012年11月8日木曜日

指定したフォルダの特定のファイルをSJISからUTF8に変更する

今の仕事で使用した、SJIS→UTF8のチャラツール。
ファイル数がすくなければ、手作業でするけど、ファイル数が多いのファイルが
サブディレクトリにわたるので、作ってみた。
諸般の事情により、Delphi2007で作ったので、UTF8への変換にはjclUnicodeの
TWideStringList、ファイルの走査にはJclFileUtilsのTJclFileEnumeratorを利用した。
(変換元ファイルのディレクトリ、変換先のディレクトリの指定にJvclの TJvDirectoryEdit
を使用した。)

以下ソースコード。


unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs,JclStrings, JclFileUtils, StdCtrls, Mask, JvExMask, JvToolEdit,jclUnicode;

type
  TForm1 = class(TForm)
    Label1: TLabel;
    Label2: TLabel;
    JvDirectoryEdit1: TJvDirectoryEdit;
    JvDirectoryEdit2: TJvDirectoryEdit;
    Button1: TButton;
    Memo1: TMemo;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
    FFileEnumerator: TJclFileEnumerator;
    FDirCount: Integer;
    FTaskID: TFileSearchTaskID;
    FT0: TDateTime;
    procedure DirectoryEntered(const Directory: string);
    procedure AddFile(const Directory: string; const FileInfo: TSearchRec);
    procedure TaskDone(const ID: TFileSearchTaskID; const Aborted: Boolean);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation
uses Types,StrUtils, VBLikeString;
{$R *.dfm}

{ TForm1 }

procedure TForm1.AddFile(const Directory: string; const FileInfo: TSearchRec);
var
  SourceFileName,TargetFileName : String;
  TargetDir : String;
  SourceText : TStringList;
  TargetText : TWideStringList;
  LineCount : Integer;
  WorkStrings : TStringDynArray;
  //RevArray : Array of String;
  RevisionString : String;
  IsHeaderArea : Boolean;
begin
  SourceFileName := Directory + FileInfo.Name;

  //変換後ファイルの書き込み先フォルダは、元ファイルのフルパスの変換元フォルダに指定した
  //文字列を変換後に指定したフォルダに置換すれば良い
  TargetFileName := ReplaceText(SourceFileName,JvDirectoryEdit1.Text,JvDirectoryEdit2.Text);
  TargetDir := ExtractFileDir(TargetFileName);

  //ディレクトリがなければ作成する
  if not(DirectoryExists(TargetDir)) then ForceDirectories(TargetDir);

  SourceText := TStringList.Create;
  try
    SourceText.LoadFromFile(SourceFileName);
    TargetText := TWideStringList.Create;
    try
      //TargetText.Text := ReplaceStr(SourceText.Text,'@CRLF',sLineBreak);
      TargetText.Text := SourceText.Text;
      TargetText.SaveUnicode := true;
      TargetText.SaveFormat := sfUTF8;
      TargetText.SaveToFile(TargetFileName);
    finally
      TargetText.Free;
    end;
  finally
    SourceText.Free;
  end;
  Memo1.Lines.Add(SourceFileName);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  RootDirectories: TStrings;
begin

  FFileEnumerator.SearchOption[fsLastChangeAfter] := false;
  FFileEnumerator.SearchOption[fsLastChangeBefore] := false;

  RootDirectories := TStringList.Create;
  try
    StrToStrings(JvDirectoryEdit1.Text, DirSeparator, RootDirectories, False);
    FFileEnumerator.RootDirectories := RootDirectories;
  finally
    RootDirectories.Free;
  end;
  FFileEnumerator.FileMask := '*.c;*.h';
  FFileEnumerator.SearchOption[fsMinSize] := false;
  FFileEnumerator.SearchOption[fsMaxSize] := false;
  FFileEnumerator.IncludeSubDirectories := true;
  FFileEnumerator.IncludeHiddenSubDirectories := true;
  FFileEnumerator.CaseSensitiveSearch := false;
  FDirCount := 0;

  FT0 := Now;
  FTaskID := FFileEnumerator.ForEach(AddFile);

end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  FFileEnumerator.StopTask(FTaskID);
end;

procedure TForm1.DirectoryEntered(const Directory: string);
begin
  Inc(FDirCount);
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  FFileEnumerator.Free;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  FFileEnumerator := TJclFileEnumerator.Create;
  FFileEnumerator.OnEnterDirectory := DirectoryEntered;
  FFileEnumerator.OnTerminateTask := TaskDone;

end;

procedure TForm1.TaskDone(const ID: TFileSearchTaskID; const Aborted: Boolean);
begin
  //
end;

end.

TJclFileEnumeratorは、ファイル検索の条件を設定したうえで、検索条件に該当するファイルが
見つかった場合に呼び出すメソッドを指定してForEcahメソッドを実行すれば、都度、指定した
メソッドを呼び出してくれるので、ForEachに指定しメソッドにSJIS→UTF8の変換処理を
書けばよい。(ソース上ではAddFile)

TStringListを使ってファイルを読み込み、そのテキストをTWideStringListに
渡して、 をTWideStringListでUTF-8を指定して保存することにより、UTF-8変換を
実施した。(このへんは、Delphi 2009以降ならもっとスマートにできる思う。)


0 件のコメント: