Delphi - tfilestream:将时间和日期写入文件
Delphi - tfilestream: write time and date to file
我正在尝试为每个事件保存一行,其中包含一段文本以及发生的时间和日期。
问题是:
- 时间显示为中文字体
- 它一遍又一遍地替换同一行
代码如下:
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;
谢谢。
通常当您希望看到拉丁文本,但看到中文文本时,这意味着您正在将 ANSI 文本解释为 UTF-16。由此我推断您打算写出 UTF-16 文本,但实际上是在写出 ANSI 文本。这意味着你有一个前 Unicode Delphi.
至于你为什么一直覆盖文件,那是因为你通过了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 版本。并始终明确说明您的目标。
关于您的代码,我要更改几处。
你有一个函数应该是 return 布尔值,但你从未设置 return 值。
不是"wrong",而是变量i
最常用作数组的整数索引,或循环变量。 Delphi 开发人员会讨厌使用 i
作为字符串的代码。
您似乎只是在记录文本。 TFileStream 可能不是最好的class。
我认为这是更简洁的代码:
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
这个怎么样:
uses SysUtils;
var s: AnsiString;
s := FormatDateTime('yyyy-mm-dd hh:nn:ss', now);
fs.Write(s[1], Length(s));
我正在尝试为每个事件保存一行,其中包含一段文本以及发生的时间和日期。
问题是:
- 时间显示为中文字体
- 它一遍又一遍地替换同一行
代码如下:
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;
谢谢。
通常当您希望看到拉丁文本,但看到中文文本时,这意味着您正在将 ANSI 文本解释为 UTF-16。由此我推断您打算写出 UTF-16 文本,但实际上是在写出 ANSI 文本。这意味着你有一个前 Unicode Delphi.
至于你为什么一直覆盖文件,那是因为你通过了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 版本。并始终明确说明您的目标。
关于您的代码,我要更改几处。
你有一个函数应该是 return 布尔值,但你从未设置 return 值。
不是"wrong",而是变量
i
最常用作数组的整数索引,或循环变量。 Delphi 开发人员会讨厌使用i
作为字符串的代码。您似乎只是在记录文本。 TFileStream 可能不是最好的class。
我认为这是更简洁的代码:
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
这个怎么样:
uses SysUtils;
var s: AnsiString;
s := FormatDateTime('yyyy-mm-dd hh:nn:ss', now);
fs.Write(s[1], Length(s));