我写了一个Pascal函数来替换文件中的整行或者只是其中的一部分,以便在Inno Setup中使用:
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,并替换了。那是我添加重复循环的时候。逻辑是Pos()
在没有找到更多事件时返回0。然后它应该继续到下一行。然而事实是,循环一直在无限进行,我不知道为什么。我尝试在Break
的{{1}}条款中添加else
语句,但没有运气......
编辑:显然已经很晚了。我用一个很长的字符串替换了OldLinePart ......它包含了相同的单词。
问题已解决如下。
if FoundAtPos > 0
答案 0 :(得分:2)
我只需拨打一次StringReplace即可取代您的循环。这可以防止(无限)循环并解决问题
请注意,您IsReplaced
也遇到问题,例如FileLines[4]
已被替换,但FilesLine[last]
未被SaveStringsToFile
替换,您的代码将不会调用uses SysUtils;
function ReplaceInFile(const FilePath, OldLinePart, Replacement: String;
DoReplaceWholeLine, IsCaseSensitive: Boolean): Boolean;
var
FileLines: TArrayOfString;
Index: Integer;
TempStr: String;
IsReplaced: Boolean;
Flags: TReplaceFlags;
IsReplacedAnywhere: Boolean;
begin
Result := False;
if FileExists(FilePath) then begin
LoadStringsFromFile(FilePath, FileLines);
IsReplacedAnywhere:= false;
for Index := 0 to GetArrayLength(FileLines) - 1 do begin
if DoReplaceWholeLine then begin
IsReplaced :=
IsCaseSensitive and (Pos(OldLinePart, FileLines[Index]) > 0) or
not(IsCaseSensitive) and
(Pos(Uppercase(OldLinePart), Uppercase(FileLines[Index])) > 0);
if IsReplaced then FileLines[Index] := Replacement;
end
else begin
Flags:= [rfReplaceAll];
if not(IsCaseSensitive) then Flags:= Flags + [rfIgnoreCase];
TempStr:= StringReplace(FileLines[Index], OldLinePart, Replacement
,Flags);
IsReplaced := (TempStr <> FileLines[Index]);
if IsReplaced then FileLines[Index]:= TempStr;
end; {else}
IsReplacedAnywhere:= IsReplacedAnywhere or IsReplaced;
end; {for Index}
Result:= IsReplacedAnywhere
and SaveStringsToFile(FilePath, FileLines, False);
end; {if}
end;
它也稍微简化了代码。
{{1}}
请告诉我这是否适合您。
答案 1 :(得分:0)
现在应该使用StringChangeEx完成。很高兴它支持Unicode。通过删除旧功能打破旧脚本的方式并不好。 StringReplace不再编译;即使这是Delphi的功能。 StringChange已被弃用。