[英]Lazarus: StringReplace ineffective when working with files (unicode issue)
我正在使用Lazarus构建一个简单的应用程序,该应用程序基于模板构建Outlook签名。 这个想法是提取模板(一个ZIP文件),并替换其中包含的文件中的变量。
例如,我可能想用用户提供的名称替换{fullname}
。
我目前正在使用下面的实现,但是它似乎无效。 该文件已被读取和写入,但似乎没有进行替换。 我已经测试过看看我的TFileStream
实现是否不正确,但是使用WriteAnsiString
将伪文本附加到输出文件的末尾是WriteAnsiString
。
请您在下面查看我的代码,让我知道我做错了什么,或者是否有替代StringReplace
更好的选择? 我知道一个人可以使用TStringList
但是,这样做会破坏行尾。 由于备忘录和丰富的编辑使用TStringList
,因此使用它们也无济于事。
更新:
我已经看到了 ,但是使用AnsiString
没什么区别。 如果我没记错的话,FPC还是会默认使用它,而不是UnicodeString
。
更新2:
实际上, 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保存了它使用不同编码创建的三个文件这一事实。 要解决它,我只是用convertEncoding
和guessEncoding
从lconvencoding
,如下图所示:
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)有些头痛。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.