Я использую Lazarus для создания простого приложения, которое строит подписи Outlook на основе шаблона. Идея состоит в том, чтобы извлечь шаблон (ZIP-файл) и заменить переменные в файлах, которые он содержит.Lazarus: StringReplace неэффективен при работе с файлами (проблема с unicode)
Например, я могу заменить {fullname}
на имя, предоставленное пользователем.
В настоящее время я использую реализацию ниже, но это кажется неэффективным. Файл читается и записывается, но, похоже, замены не выполняются. Я проверил, не работает ли моя реализация TFileStream
, но с помощью WriteAnsiString
для добавления фиктивного текста в конец выходного файла.
Прошу вас, пожалуйста, взглянуть на мой код ниже и сообщить мне, что я, возможно, сделал не так, или если есть какие-то лучшие альтернативы StringReplace
? Я знаю, что можно использовать TStringList
, но при этом прерывается окончание строк. В качестве заметок и расширенных изменений используется TStringList
, использование которых тоже не поможет.
Update:
Я видел this, но с использованием AnsiString
не имеет никакого значения. Если я не ошибаюсь, FPC использует его по умолчанию в любом случае, а не UnicodeString
.
Update 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']);
Ваш файл шаблона содержит текст UTF16? Если да - попробуйте перекодировать его в UTF8 (собственное кодирование для Lazarus). – Abelisto
Похоже, что файл '.txt', создаваемый Outlook Outlook, действительно UTF-16LE (в то время как файл' .htm' - это Windows-1252). Как я могу кодировать кодировку соответствующего файла и преобразовывать соответственно? –
О перекодировке текста вы можете прочитать здесь [здесь] (http://wiki.lazarus.freepascal.org/Multiplatform_Programming_Guide#Text_encoding). Однако для моего маленького тестового файла в UTF-16LE функция 'GuessEncoding' возвращает' utf8' по неизвестной причине.Использование кодирования с жестким кодированием отлично работает: 'ShowMessage (ConvertEncoding (s, EncodingUCS2LE, EncodingUTF8));' Не забудьте использовать блок LConvEncoding. – Abelisto