多个 TFileStreams,TStreamWriter 写入同一个文件

Multiple TFileStreams, TStreamWriter writing to same file

我开始使用 TFileStreamTStreamWriter 来编写简单的文本日志文件(而不是旧的 Writeln(T,....))。我有多个应用程序写入同一个日志文件。 当然,每个应用程序都有自己的 TFileStream,它们每个都这样打开文件

FFileStream:=TFileStream.Create(LogName, fmOpenReadWrite+fmShareDenyNone)
FExporter:=TStreamWriter.Create(FFilestream, TEncoding.UTF8);
FExporter.NewLine:=#[=10=]A;
FExporter.AutoFlush:=TRUE;

并使用

写入文件
  FExporter.BaseStream.Seek(0, soFromEnd);
  FExporter.Write('['+DateToStr(Now, FDateTimeFormat)+'] ['+TimeToStr(Now, FDateTimeFormat)+'] [#'+Lead0(GetCurrentThreadId, 5)+']: '+EntryText);
  FExporter.WriteLine;

结果有点“不尽如人意”,因为线条错位,中间有空行,似乎不起作用。

我该如何正确地做到这一点?

在多个进程中同时写入多行可能会导致意外继续,因为并行执行。

您应该确保您正在连续写入一个块,因此 WriteLine 应该在最后使用 lineBreak 在写入内部发送。

所以你的写法应该是:

  FExporter.BaseStream.Seek(0, soFromEnd);
  FExporter.Write('['+DateToStr(Now, FDateTimeFormat)+'] ['+TimeToStr(Now, FDateTimeFormat)+'] [#'+Lead0(GetCurrentThreadId, 5)+']: '+EntryText + System.slineBreak);
  //FExporter.WriteLine;

更新1: 正如 link Oliver 发布的那样,如果要写入的消息大小大于 OS 文件扇区,有时它无法工作,并且在那一刻,其他进程也尝试写入消息。因此在这种情况下,结果内容可能是混合的。

所以按照我的第一个目的,您会增加获得所需结果的可能性,但在 100% 的情况下可能不是解决方案。

要 100% 确定在单个文件中写入连续日志,使用多进程,您应该创建一个日志进程来接收来自其他进程的消息,并唯一负责在整个线程中写入同步日志。