Delphi - tfilestream: записать время и дату в файл
Я пытаюсь сохранить строку для каждого события, содержащую фрагмент текста и время + дату, когда произошло.
Проблема в:
- время показывается китайским шрифтом
- он заменяет одну и ту же строку снова и снова
Вот код:
uses sysUtils, classes;
function log: Boolean;
var
fs: TFileStream;
i : String;
time : TDateTime;
begin
i := 'Boss is dead!';
time := now;
try
fs := TFileStream.Create('log.txt', fmCreate or fmOpenWrite);
fs.Write(PChar(i +TimeToStr(time))^, Length(i +TimeToStr(time)));
fs.write(i, sizeof(i));
finally
fs.Free;
end;
end;
Спасибо.
3 ответа
Обычно, когда вы ожидаете текст на латинице, но видите текст на китайском языке, это означает, что вы интерпретируете текст ANSI, как если бы он был UTF-16. Из этого я делаю вывод, что вы намерены записать текст UTF-16, но на самом деле пишете текст ANSI. Это означает, что у вас есть Delphi до Unicode.
Что касается того, почему вы продолжаете перезаписывать файл, то это потому, что вы передаете fmCreate
, Что вы действительно хотите сделать, так это открыть существующий файл в режиме записи или, если файл не существует, создать новый файл. Функция Win32 API поддерживает это с OPEN_ALWAYS
творческий нрав. Но это не доступно через TFileStream.Create
, Так что вы должны использовать THandleStream
и позвонить CreateFile
непосредственно. Обратите внимание, что более новые версии Delphi представляют TFile.Open
что разоблачает OPEN_ALWAYS
функциональность. Но мои рассуждения говорят, что вы используете Delphi, который слишком стар.
Предполагая, что вы можете использовать THandleStream
и позвоните CreateFile
правильно, тогда вам просто нужно выписать текст UTF-16. Самый простой способ - это использовать WideString
, Вы можете написать код так:
var
ws: WideString;
....
Stream.Seek(0, soFromEnd);
ws := TimeToStr(Now) + sLineBreak;
Stream.WriteBuffer(PWideChar(ws)^, SizeOf(WideChar)*Length(ws));
С другой стороны, возможно, китайцы пришли отсюда:
fs.write(i, sizeof(i));
Этот код просто записывает указатель на файл. Вы точно не хотите этого делать и должны удалить эту строку. Для полноты картины, если у вас есть Unicode Delphi, вы бы написали текст очень похожим образом. Как это:
var
s: string;
....
Stream.Seek(0, soFromEnd);
s := TimeToStr(Now) + sLineBreak;
Stream.WriteBuffer(PWideChar(s)^, SizeOf(WideChar)*Length(s));
Возвращаясь к добавлению в поток, он будет работать так:
var
hFile: THandle;
....
hFile := CreateFile(
PChar(LogFileName),
GENERIC_WRITE,
FILE_SHARE_READ,
nil,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
0
);
Win32Check(hFile<>INVALID_HANDLE_VALUE);
Try
Stream := THandleStream.Create(hFile);
Try
.... code to write to the stream goes here
Finally
Stream.Free;
End;
Finally
CloseHandle(hFile);
End;
Наконец, я должен был сделать много предположений о вашей среде в этом ответе. В будущем всегда включайте версию Delphi, которую вы используете. И всегда включайте четкое изложение ваших целей.
Как насчет этого:
uses SysUtils;
var s: AnsiString;
s := FormatDateTime('yyyy-mm-dd hh:nn:ss', now);
fs.Write(s[1], Length(s));
Есть несколько вещей, которые я бы изменил в вашем коде.
У вас есть функция, которая должна возвращать логическое значение, но вы никогда не устанавливаете возвращаемое значение.
Это не "неправильно", а переменная
i
чаще всего используется как целочисленный индекс для массива или как переменная цикла. Разработчики Delphi будут ненавидеть код, который используетi
как строкаПохоже, вы просто записываете текст. TFileStream, вероятно, не лучший класс для этого.
Я думаю, что это намного чище код:
uses System.IoUtils;
...
FileName := 'log.txt';
LogLine := 'Boss is dead '+TimeToStr(Now);
TFile.AppendAllText(FileName, LogLine);
http://docwiki.embarcadero.com/Libraries/XE7/en/System.IOUtils.TFile.AppendAllText