Inno Setup で使用するために、ファイル内の行全体またはその一部を置き換える Pascal 関数を作成しました。
function ReplaceInFile(const FilePath, OldLinePart, Replacement: String;
DoReplaceWholeLine, IsCaseSensitive: Boolean): Boolean;
var
FileLines: TArrayOfString;
Index: Integer;
FoundAtPos: Integer;
LeftOfOldLinePart: String;
RightOfOldLinePart: String;
IsReplaced: Boolean;
begin
Result := False;
if FileExists(FilePath) then begin
LoadStringsFromFile(FilePath, FileLines);
for Index := 0 to GetArrayLength(FileLines) - 1 do
begin
repeat
FoundAtPos := 0;
if IsCaseSensitive then
FoundAtPos := Pos(OldLinePart, FileLines[Index])
else
FoundAtPos := Pos(Uppercase(OldLinePart), Uppercase(FileLines[Index]));
if FoundAtPos > 0 then begin
if DoReplaceWholeLine then begin
FileLines[Index] := Replacement;
IsReplaced := True;
end
else begin
LeftOfOldLinePart := Copy(FileLines[Index], 1, FoundAtPos - 1);
RightOfOldLinePart := Copy(FileLines[Index], FoundAtPos
+ Length(OldLinePart), Length(FileLines[Index])
- Length(LeftOfOldLinePart + OldLinePart));
FileLines[Index] := LeftOfOldLinePart + Replacement + RightOfOldLinePart;
IsReplaced := True;
end;
end;
until FoundAtPos = 0;
end;
if IsReplaced then
if SaveStringsToFile(FilePath, FileLines, False) then
Result := True;
end;
end;
以前は問題なく動作していましたが、FilePath で指定されたファイルの各行で最初に出現した OldLinePart のみを Replacement に置き換えていました。それが繰り返しループを追加したときです。Pos()
これ以上オカレンスが見つからない場合、ロジックは 0 を返します。その後、次の行に進む必要があります。しかし、真実はループが無限に続き、その理由がわかりません。の句にBreak
ステートメントを追加しようとしましたが、うまくいきません...else
if FoundAtPos > 0
追記:明らかに遅くなりました。OldLinePart を非常に長い文字列に置き換えていました...同じ単語が含まれていました。
この問題は次のように解決されました。
function ReplaceInFile(const FilePath, OldLinePart, Replacement: String; DoReplaceWholeLine, IsCaseSensitive: Boolean): Boolean;
var
FileLines: TArrayOfString;
Index: Integer;
SearchLinePart: String;
FoundAtPosition: Integer;
SearchOffset: Integer;
LeftOfOldLinePart: String;
RightOfOldLinePart: String;
IsReplaced: Boolean;
begin
Result := False;
if FileExists(FilePath) then
begin
LoadStringsFromFile(FilePath, FileLines);
for Index := 0 to GetArrayLength(FileLines) - 1 do
begin
SearchOffset := 0;
SearchLinePart := FileLines[Index];
repeat
FoundAtPosition := 0;
if IsCaseSensitive then
FoundAtPosition := SearchOffset + Pos(OldLinePart, SearchLinePart)
else
FoundAtPosition := SearchOffset + Pos(Uppercase(OldLinePart), Uppercase(SearchLinePart));
if FoundAtPosition > SearchOffset then
begin
if DoReplaceWholeLine then
begin
FileLines[Index] := Replacement;
IsReplaced := True;
Break;
end
else
begin
LeftOfOldLinePart := '';
RightOfOldLinePart := '';
LeftOfOldLinePart := Copy(FileLines[Index], 1, FoundAtPosition - 1);
RightOfOldLinePart := Copy(FileLines[Index], FoundAtPosition + Length(OldLinePart), Length(FileLines[Index]) - Length(LeftOfOldLinePart + OldLinePart));
FileLines[Index] := LeftOfOldLinePart + Replacement + RightOfOldLinePart;
IsReplaced := True;
SearchOffset := Length(LeftOfOldLinePart + Replacement);
SearchLinePart := RightOfOldLinePart;
end;
end;
until FoundAtPosition <= SearchOffset;
end;
if IsReplaced then
if SaveStringsToFile(FilePath, FileLines, False) then
Result := True;
end;
end;