delphi - TStreamWriter 锁定文件以供读取
问题描述
在我们的项目中,我们使用 StreamWriter 写入日志文件。
在写作时,我想在文件中搜索一些特定的行。例如在单元测试期间。但不知何故,我无法从文件中读取,因为它被进程阻止了。我不明白它为什么被阻止,因为我认为我打开 FileStream 时没有任何阻塞。
我将所有内容从项目中提取到这个小例子中。在写入文件时,我必须更改什么以不阻止文件读取?
program Playground;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils, System.Classes;
var
FileStream: TFileStream;
FileStreamWriter : TStreamWriter;
strList: TStringList;
fileName: String;
begin
try
strList := TStringList.Create;
fileName := 'TestFile.txt';
FileStream := TFileStream.Create(fileName, fmCreate or fmShareDenyNone);
FileStreamWriter := TStreamWriter.Create(FileStream, TEncoding.Unicode);
FileStreamWriter.WriteLine('12345');
strList.LoadFromFile(fileName); // Crashes because a proccess blocks the file
strList.Free;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
Readln;
end.
解决方案
正如 Peter Wolf 在他的评论中所说的那样,造成您的麻烦的原因不在于您的代码,而在于StringList.LoadFromFile
代码。
当字符串列表试图加载文件的内容时,您会看到它以一种会阻止其他应用程序读取其内容的方式打开它。
下面是StringList.LoadFromFile
代码的样子:
procedure TStrings.LoadFromFile(const FileName: string);
var
Stream: TStream;
begin
Stream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
try
LoadFromStream(Stream);
finally
Stream.Free;
end;
end;
因此,为了避免这个问题,您应该自己创建另一个文件流,然后使用该文件流将文件内容读入StringList
.
program Playground;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils, System.Classes;
var
FileStream: TFileStream;
StrListFS: TFileStream;
FileStreamWriter : TStreamWriter;
strList: TStringList;
fileName: String;
begin
try
strList := TStringList.Create;
fileName := 'D:\TestFile.txt';
FileStream := TFileStream.Create(fileName, fmCreate or fmShareDenyNone);
FileStreamWriter := TStreamWriter.Create(FileStream, TEncoding.Unicode);
FileStreamWriter.WriteLine('12345');
//strList.LoadFromFile(fileName); // Crashes because a proccess blocks the file
//Create a new file stream that we will use for reading the file contents into
//our string list.
StrListFS := TFileStream.Create(fileName, fmOpenRead or fmShareDenyNone);
//Load contets from a file into a stream by using our newly created FileStream
strList.LoadFromStream(StrListFS);
//Free the file stream when we are done loading the data.
StrListFS.Free;
strList.Free;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
Readln;
end.
理论上,您可以使用流编写器使用的相同文件流将该文件的内容读入字符串列表,但请注意这样做会改变您的流位置,因此您必须保存之前的位置并在读取后恢复它将文件的内容添加到字符串列表中。
即使您以锁定模式打开流编写器文件流,这种方式也可以做到这一点,这将阻止多个进程/句柄打开文件。
推荐阅读
- python - 在 python 套接字库文档中,`bufsize[, flags]` 是什么意思?
- c++ - 如何有一个向量的复制构造函数?
- getstream-io - 如何从频道中删除用户
- java - 从 JSON API 获取数据并循环放入 CSV
- python - 在python中打印矩阵(2-d)
- reactjs - 如何将 xxl 和 xxxl 引导断点添加到 react-strap 应用程序
- python - 减少python中嵌套循环的时间复杂度
- konvajs - 有没有办法更具体地控制 konva 对象的拖动事件?
- laravel - 无法在 Virtualbox 上启动虚拟机 - Ubuntu 18.04 - 臭名昭著的问题 - 没有解决方案有效
- javascript - React Native 上的 XSLT 处理器(从 XML 到 HTML)