TStreamWriter 锁定文件以供读取
TStreamWriter locks file for Read
在我们的项目中,我们使用 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.
理论上,您可以使用流编写器使用的相同文件流将该文件的内容读入字符串列表,但请注意,这样做会改变您的流位置,因此您必须先保存之前的位置并在将文件内容读入字符串列表后恢复它。
即使您以锁定模式打开流写入器文件流,这种方式也可以做到这一点,这会阻止多个文件打开 processes/handles。
在我们的项目中,我们使用 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.
理论上,您可以使用流编写器使用的相同文件流将该文件的内容读入字符串列表,但请注意,这样做会改变您的流位置,因此您必须先保存之前的位置并在将文件内容读入字符串列表后恢复它。
即使您以锁定模式打开流写入器文件流,这种方式也可以做到这一点,这会阻止多个文件打开 processes/handles。