Lazarus:处理文件时 StringReplace 无效(unicode 问题)

Lazarus: StringReplace ineffective when working with files (unicode issue)

我正在使用 Lazarus 构建一个基于模板构建 Outlook 签名的简单应用程序。这个想法是提取模板(一个 ZIP 文件),并替换它包含的文件中的变量。

例如,我可能想用用户提供的名称替换{fullname}

我目前正在使用下面的实现,但似乎没有效果。该文件已读取和写入,但似乎没有进行替换。我已经测试过我的 TFileStream 实现是否不正确,但是使用 WriteAnsiString 将虚拟文本附加到输出文件的末尾是可行的。

请您看看我下面的代码,让我知道我可能做错了什么,或者是否有比 StringReplace 更好的替代方法?我知道可以使用 TStringList - 但是,这样做会破坏行尾。由于备忘录和丰富的编辑使用 TStringList,使用它们也无济于事。

更新:

我看过this,但使用AnsiString没有区别。如果我没记错的话,反正FPC默认是用的,而不是UnicodeString.

更新二:

确实,AnsiString 是默认值。使用 unicode 字符串(使替换起作用)将 ? 添加到文件的开头和结尾。为什么要这样做?


function multiStringReplace(const s: string; search, replace : array of string; flags : tReplaceFlags): string;
var c : cardinal;
begin
    assert(length(search) = length(replace), 'Array lengths differ.');
    result := s;
    for c := low(search) to high(search) do
        result := stringReplace(result, search[c], replace[c], flags);
end;
procedure fileReplaceString(const fileName: string; search, replace: array of string);
var
    fs: tFileStream;
    s: string;
begin
    fs := tFileStream.create(fileName, fmOpenRead or fmShareDenyNone);
    try
        setLength(s, fs.size);
        fs.readBuffer(s[1], fs.size);
    finally
        fs.free();
    end;
    s := multiStringReplace(s, search, replace, [rfReplaceAll, rfIgnoreCase]);
    fs := tFileStream.create(fileName, fmOpenWrite);
    try
        fs.writeBuffer(s[1], length(s));
    finally
        fs.free();
    end;
end;

用法:

fileReplaceString(currentFile, ['{fullname}'], ['Full Name']);

感谢 Abelisto 上面的评论,问题似乎是因为 Outlook 保存了它使用不同编码创建的三个文件。为了解决这个问题,我简单地使用了 lconvencoding 中的 convertEncodingguessEncoding,如下所示:

uses
    lconvencoding;
// Read string
s := convertEncoding(
    multiStringReplace(s, search, replace, [rfReplaceAll, rfIgnoreCase]),
    guessEncoding(s), encodingAnsi
);
// Write modified and converted string back to file

encodingAnsi 似乎是最好的转换,至少在我看来是这样。转换为 UTF8(有或没有 BOM)导致某些字符有点头疼,特别是 EmDash 或 EnDash。