2012年11月8日木曜日

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

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

以下ソースコード。


  1. unit Unit1;  
  2.   
  3. interface  
  4.   
  5. uses  
  6.   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,  
  7.   Dialogs,JclStrings, JclFileUtils, StdCtrls, Mask, JvExMask, JvToolEdit,jclUnicode;  
  8.   
  9. type  
  10.   TForm1 = class(TForm)  
  11.     Label1: TLabel;  
  12.     Label2: TLabel;  
  13.     JvDirectoryEdit1: TJvDirectoryEdit;  
  14.     JvDirectoryEdit2: TJvDirectoryEdit;  
  15.     Button1: TButton;  
  16.     Memo1: TMemo;  
  17.     Button2: TButton;  
  18.     procedure Button1Click(Sender: TObject);  
  19.     procedure FormCreate(Sender: TObject);  
  20.     procedure FormClose(Sender: TObject; var Action: TCloseAction);  
  21.     procedure Button2Click(Sender: TObject);  
  22.   private  
  23.     { Private declarations }  
  24.     FFileEnumerator: TJclFileEnumerator;  
  25.     FDirCount: Integer;  
  26.     FTaskID: TFileSearchTaskID;  
  27.     FT0: TDateTime;  
  28.     procedure DirectoryEntered(const Directory: string);  
  29.     procedure AddFile(const Directory: stringconst FileInfo: TSearchRec);  
  30.     procedure TaskDone(const ID: TFileSearchTaskID; const Aborted: Boolean);  
  31.   public  
  32.     { Public declarations }  
  33.   end;  
  34.   
  35. var  
  36.   Form1: TForm1;  
  37.   
  38. implementation  
  39. uses Types,StrUtils, VBLikeString;  
  40. {$R *.dfm}  
  41.   
  42. { TForm1 }  
  43.   
  44. procedure TForm1.AddFile(const Directory: stringconst FileInfo: TSearchRec);  
  45. var  
  46.   SourceFileName,TargetFileName : String;  
  47.   TargetDir : String;  
  48.   SourceText : TStringList;  
  49.   TargetText : TWideStringList;  
  50.   LineCount : Integer;  
  51.   WorkStrings : TStringDynArray;  
  52.   //RevArray : Array of String;  
  53.   RevisionString : String;  
  54.   IsHeaderArea : Boolean;  
  55. begin  
  56.   SourceFileName := Directory + FileInfo.Name;  
  57.   
  58.   //変換後ファイルの書き込み先フォルダは、元ファイルのフルパスの変換元フォルダに指定した  
  59.   //文字列を変換後に指定したフォルダに置換すれば良い  
  60.   TargetFileName := ReplaceText(SourceFileName,JvDirectoryEdit1.Text,JvDirectoryEdit2.Text);  
  61.   TargetDir := ExtractFileDir(TargetFileName);  
  62.   
  63.   //ディレクトリがなければ作成する  
  64.   if not(DirectoryExists(TargetDir)) then ForceDirectories(TargetDir);  
  65.   
  66.   SourceText := TStringList.Create;  
  67.   try  
  68.     SourceText.LoadFromFile(SourceFileName);  
  69.     TargetText := TWideStringList.Create;  
  70.     try  
  71.       //TargetText.Text := ReplaceStr(SourceText.Text,'@CRLF',sLineBreak);  
  72.       TargetText.Text := SourceText.Text;  
  73.       TargetText.SaveUnicode := true;  
  74.       TargetText.SaveFormat := sfUTF8;  
  75.       TargetText.SaveToFile(TargetFileName);  
  76.     finally  
  77.       TargetText.Free;  
  78.     end;  
  79.   finally  
  80.     SourceText.Free;  
  81.   end;  
  82.   Memo1.Lines.Add(SourceFileName);  
  83. end;  
  84.   
  85. procedure TForm1.Button1Click(Sender: TObject);  
  86. var  
  87.   RootDirectories: TStrings;  
  88. begin  
  89.   
  90.   FFileEnumerator.SearchOption[fsLastChangeAfter] := false;  
  91.   FFileEnumerator.SearchOption[fsLastChangeBefore] := false;  
  92.   
  93.   RootDirectories := TStringList.Create;  
  94.   try  
  95.     StrToStrings(JvDirectoryEdit1.Text, DirSeparator, RootDirectories, False);  
  96.     FFileEnumerator.RootDirectories := RootDirectories;  
  97.   finally  
  98.     RootDirectories.Free;  
  99.   end;  
  100.   FFileEnumerator.FileMask := '*.c;*.h';  
  101.   FFileEnumerator.SearchOption[fsMinSize] := false;  
  102.   FFileEnumerator.SearchOption[fsMaxSize] := false;  
  103.   FFileEnumerator.IncludeSubDirectories := true;  
  104.   FFileEnumerator.IncludeHiddenSubDirectories := true;  
  105.   FFileEnumerator.CaseSensitiveSearch := false;  
  106.   FDirCount := 0;  
  107.   
  108.   FT0 := Now;  
  109.   FTaskID := FFileEnumerator.ForEach(AddFile);  
  110.   
  111. end;  
  112.   
  113. procedure TForm1.Button2Click(Sender: TObject);  
  114. begin  
  115.   FFileEnumerator.StopTask(FTaskID);  
  116. end;  
  117.   
  118. procedure TForm1.DirectoryEntered(const Directory: string);  
  119. begin  
  120.   Inc(FDirCount);  
  121. end;  
  122.   
  123. procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);  
  124. begin  
  125.   FFileEnumerator.Free;  
  126. end;  
  127.   
  128. procedure TForm1.FormCreate(Sender: TObject);  
  129. begin  
  130.   FFileEnumerator := TJclFileEnumerator.Create;  
  131.   FFileEnumerator.OnEnterDirectory := DirectoryEntered;  
  132.   FFileEnumerator.OnTerminateTask := TaskDone;  
  133.   
  134. end;  
  135.   
  136. procedure TForm1.TaskDone(const ID: TFileSearchTaskID; const Aborted: Boolean);  
  137. begin  
  138.   //  
  139. end;  
  140.   
  141. end.  

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

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


0 件のコメント: