Delphiメモ

No027:iniファイルに複数行文字列を保存する

以下のような文字列があったとする。

これは、
複数行テキスト保存の、
テストなのだ!!

これをファイルとして保存する手段はいろいろある。
もちろんiniファイルも手段の1つであるが、普通にWriteStringで保存すると困ったことが起こる。
試しにこんな感じで保存してみる。

var
  ini: TIniFile;
begin
  ini:= TIniFile.Create(ChangeFileExt(Application.ExeName,'.ini'));
  try
    ini.WriteString('Test','String','これは'+#13#10+'複数行テキスト保存の'+#13#10+'テストなのだ!!');
  finally
    ini.Free;
  end;
end;

このコードを実行しても何らエラーは発生しない。
iniファイルを開いてみてもちゃんと保存されている。
しかし、これを読み込んでみると以下の文字列しか読み込まれない。

これは

なぜなのか?iniファイルをよく見てよう。

[Test]
String=これは
複数行テキスト保存の、
テストなのだ!!

一見なんて事無いように見えているが、実は大問題がある。
すべてのiniファイルは情報を「セクション」という論理的なグループに分けて格納する。
各セクション内では実際のデータは指定のキーに格納される。そしてそのキーは次のような形式をとる。

<keyname>=<value>

このvalueは1行で収っていないといけない。
つまり2行目の「String=これは」はStringキーに格納されたデータということになるが、
3行目及び4行目はキーもなければデータもないのである。

ではどうすればいいのか。
保存しようとしている文字列は改行文字を表示すれば以下の通りである。

これは、#13#10複数行テキスト保存の、#13#10テストなのだ!!

この#13#10はCRLFということになるが、
保存する時はこれを何か別の文字列に変換してから保存すれば、1行のデータとして保存することができる。
読み出す時はCRLFに戻せば良いだけである。

そこで使うのがStringReplace関数。
文字通り文字列置換を行う関数である。
宣言は以下の通り。

function StringReplace(const S: string; const OldPattern: string;
const NewPattern: string; Flags: TReplaceFlags): string;

引数は順番に説明すると、

S:ソースとなる文字列

OldPattern:置換対象となる文字列

NewPattern:OldPatternのかわりになる文字列

Flags:検索/置換動作の制御フラグ、内容は以下の通り

rfReplaceAll:すべての文字を置換。このフラグが含まれていない場合、
対象部分文字列内の最初の文字だけを置換する。

rfIgnoreCase:部分文字列の比較は、大文字と小文字を区別しないで行う。
このフラグが含まれていない場合、部分文字列の一致は大文字と小文字を区別した比較で識別される。

つまり目的の通りに動作させるためには、
Sに「これは、#13#10複数行テキスト保存の、#13#10テストなのだ!!」を指定し、
OldePatternに#13#10、NewPatternに何か別の文字列、FlagsにrfReplaceAllを指定すればよい。

以下の例はCRLFを\nに置き換えてiniファイルに保存するコードである。

var
  ini: TIniFile;
  Src: String;
begin
  Src:= 'これは、'+#13#10+'複数行テキスト保存の、'+#13#10+'テストなのだ!!';
  Src:= StringReplace(Src,#13#10,'\n',[rfReplaceAll]);
  ini:= TIniFile.Create(ChangeFileExt(Application.ExeName,'.ini'));
  try
    ini.WriteString('Test','String',Src);
  finally
    ini.Free;
  end;
end;

保存されたiniファイルには以下のように記録される。

これは、\n複数行テキスト保存の、\nテストなのだ!!

読み出す時は以下のようにすればいい。

var
  ini: TIniFile;
  Src: String;
begin
  ini:= TIniFile.Create(ChangeFileExt(Application.ExeName,'.ini'));
  try
    Src:= ini.ReadString('Test','String','しっぱい');
  finally
    ini.Free;
  end;
  Src:= StringReplace(Src,'\n',#13#10,[rfReplaceAll]);
end;

正直、実用性があるのかどうかは疑問だなぁ。

トップに戻る

関連ページ