# Delphi のソースコードを一括で UTF-8 に変換する --- tags: Delphi programming Pascal embarcadero objectpascal created_at: 2021-11-02 updated_at: 2021-11-11 --- # はじめに Delphi のソースファイルはデフォルト ANSI コードページが使われるので、海外の方が作ったアプリのソースファイルを開くとソースコードが破壊される事があります。 また、自身で書いたコードもデフォルトでは Shift_JIS (コードページ: 932) で保存されている事になります (日本語環境をお使いの場合)。 Delphi 2005 以降 (正確には Delphi 8 以降)、ソースファイルを UTF-8 で保存する事が可能です。 ![image.png](./images/2af09797-e804-202b-a34e-abbd0588cb2a.png) 古い IDE とファイルを共有するのでもない限り、エンコーディングを Shift_JIS にする必然性はありません。 ## デフォルトのファイルエンコード デフォルトのファイルエンコードを UTF-8 に変更するにはいくつか方法があります。 ### 1. Delphi 10.4 Sydney 以降 [ツール | オプション...] でオプションダイアログを開き [ユーザーインターフェイス | エディタ] でデフォルトのファイルエンコードを指定する事ができます。 ![image.png](./images/9f08ab27-7940-0ca9-4eb7-73a0f5a29c7b.png) ### 2. UTF8ize Plugin (Delphi 2010 ~ 10.3 Rio) **UTF8ize Plugin** を導入すると、新規に作成したり開いたユニットのファイルエンコードが UTF-8 にセットされます。 - [UTF8ize Plugin。(Swanman's Horizon)](https://lyna.hateblo.jp/entry/20150618/1434639803) - [自作プラグインの 10.3 Rio 対応状況。(Swanman's Horizon)](https://lyna.hateblo.jp/entry/20181123/1542962830) - UTF8ize plugin Ver.0.0.5 があります。 先述の通り、10.4 Sydney 以降ではオプションダイアログでデフォルトのファイルエンコードを変更できますので、UTF8ize が必要になるのは Delphi 2010 ~ 10.3 Rio という事になるかと思います。 ### 3. レジストリ Delphi 8 以降のガリレオ IDE では、レジストリを変更する事によって、デフォルトのファイルエンコードを UTF-8 に変更できます。 | Delphi | BDS バージョン | レジストリキー | |:---|:---|:---| | Delphi 8, 2005, 2006, 2007 | 2.0, 3.0, 4.0, 5.0 | HKEY_CURRENT_USER\Software\Borland | | Delphi 2009, 2010 | 6.0, 7.0 | HKEY_CURRENT_USER\Software\CodeGear | | Delphi XE 以降 | 8.0 ~ | HKEY_CURRENT_USER\Software\Embarcadero | いずれかの、`BDS\xx.x\Editor` (xx.x は BDS バージョン) にある (なければ新規作成) `DefaultFileFilter` (REG_SZ) の値を `Borland.FileFilter.ANSI` から `Borland.FileFilter.UTF8ToUTF8` に変更します。 例えば Delphi 2007 の場合、`HKEY_CURRENT_USER\Software\Borland\BDS\5.0\Editor` に `DefaultFileFilter` を新規作成してデータを `Borland.FileFilter.UTF8ToUTF8` に設定します [^1]。 ![image.png](./images/a2eda785-ac47-a99f-43ed-0b1923ce94a3.png) **See also:** - [More IDE secrets - UTF8 and the Editor (community.embarcadero.com)](https://community.embarcadero.com/blogs/entry/more-ide-secrets--utf8-and-the-editor-284) # ANSI2UTF8 Delphi のソースコードのコードページを一括で UTF-8 に変換するツールを Delphi で書いてみます。 ## ソースコード Delphi 10.3 Rio 以降でコンパイルできますが、インライン変数宣言を使わなければ Delphi XE とかでもコンパイルできると思います。 ```pascal:ANSI2UTF8.dpr program ANSI2UTF8; {$APPTYPE CONSOLE} uses System.SysUtils, System.Classes, System.IOUtils, System.StrUtils, System.WideStrUtils; const SearchOption: array [Boolean] of TSearchOption = (TSearchOption.soTopDirectoryOnly, TSearchOption.soAllDirectories); begin var Dir := ''; var Enc: TEncoding := nil; var ErrFlg := False; var IsBackup := False; var IsRecursive := False; Writeln('ANSI to UTF-8 File Converter - Copyright (c) 2021 DEKO'); repeat if ParamCount = 0 then begin ErrFlg := True; Break; end; IsBackup := FindCmdLineSwitch('b', True); IsRecursive := FindCmdLineSwitch('r', True); var sCodePage := ''; var IsCodePage := FindCmdLineSwitch('c', sCodePage); if IsCodePage then begin var CodePage := StrToIntDef(sCodePage, -1); if CodePage = -1 then begin Writeln('Invalid Codepage.'); ErrFlg := True; Break; end else Enc := TEncoding.GetEncoding(CodePage); end; Dir := ExpandFileName(ParamStr(ParamCount)); if not TDirectory.Exists(Dir) then begin Writeln('Invalid Path.'); ErrFlg := True; Break; end; until True; if ErrFlg then begin Writeln(#$0D#$0A'Usage: ' + TPath.GetFileNameWithoutExtension(ParamStr(0)) + ' [-B] [-C CodePage] [-R] ProjectDir'); Writeln(''); Writeln(' -B'#$09#$09'Create Backup File'); Writeln(' -C CodePage'#$09'Set CodePage'); Writeln(' -R'#$09#$09'Recursive'); ExitCode := -1; Exit; end; ExitCode := 1; if Enc = nil then Enc := TEncoding.GetEncoding(0); var MS := TMemoryStream.Create; var SL := TStringList.Create; try Writeln(''); for var FileName in TDirectory.GetFiles(Dir, '*.*', SearchOption[IsRecursive]) do begin var Ext := LowerCase(TPath.GetExtension(FileName)); if not MatchStr(Ext, ['.pas', '.inc', '.dpr', '.dpk']) then Continue; MS.LoadFromFile(FileName); if not HasUTF8BOM(MS) then begin MS.Position := 0; SL.LoadFromStream(MS, Enc); SL.SaveToFile(FileName, TEncoding.UTF8); if IsBackup then begin MS.Position := 0; MS.SaveToFile(FileName + '.bak'); end; Writeln(FileName); end; end; finally SL.Free; MS.Free; Enc.Free; end; ExitCode := 0; end. ``` C++ Builder にも対応させたい場合には、`MatchStr()` の所に、変換対象となるソースファイルの拡張子を追加してください。 ```pascal:ANSI2UTF8.dpr if not MatchStr(Ext, ['.pas', '.inc', '.dpr', '.dpk', '.c' , '.h' , '.cpp', '.hpp']) then Continue; ``` 何か漏れているような...? ## 使い方 `ANSI2UTF8.EXE` にプロジェクトフォルダを指定して実行します。 ```text ANSI to UTF-8 File Converter - Copyright (c) 2021 DEKO Usage: ANSI2UTF8 [-B] [-C CodePage] [-R] ProjectDir -B Create Backup File -C CodePage Set CodePage -R Recursive ``` | フラグ | 意味 | |:---|:---| | -B | 変換前のファイルを .BAK として残します | | -C CodePage | 変換前のファイルのコードページを指定します | | -R | サブフォルダ内のファイルも変換します | 普通の使い方は、 ```text ANSI2UTF8 ``` です。 サブフォルダにもソースファイルがある場合には `-R` を、海外の方が作られたプロジェクトファイルを日本語環境で変換する場合には `-C 1252` 等を指定してください [^2]。 **See also:** - [コードページ識別子 (docs.microsoft.com)](https://docs.microsoft.com/ja-jp/windows/win32/intl/code-page-identifiers) # おわりに このツールは未公開だと思って Qiita に記事を書いたのですが、やっぱり公開してました。がっでむ。 - [ソースコードをすべて UTF-8 にする (Delphi Forum)](https://ht-deko.com/delphiforum/?vasthtmlaction=viewtopic&t=1608.0) 折角なので、整理したソースコードを反映させておきました。 [^1]: Qiita の記事からコピペすると末尾にスペースが含まれがちなので注意してください。 [^2]: 何語で書かれているのかを調べ、適切なコードページを指定する必要があります。