我想逐行处理文本文件。过去,我将文件加载到 StringList
中:
slFile := TStringList.Create();
slFile.LoadFromFile(filename);
for i := 0 to slFile.Count-1 do
begin
oneLine := slFile.Strings[i];
//process the line
end;
问题是一旦文件达到几百兆字节,我就必须分配巨大内存块;实际上我只需要足够的内存一次保存一行。 (另外,当系统锁定在步骤 1 中加载文件时,您无法真正指示进度)。
我尝试使用 Delphi 提供的 native 且推荐的文件 I/O 例程:
var
f: TextFile;
begin
Reset(f, filename);
while ReadLn(f, oneLine) do
begin
//process the line
end;
Assign
的问题是没有选项可以在不锁定的情况下读取文件(即 fmShareDenyNone
)。前面的 stringlist
示例也不支持无锁,除非将其更改为 LoadFromStream
:
slFile := TStringList.Create;
stream := TFileStream.Create(filename, fmOpenRead or fmShareDenyNone);
slFile.LoadFromStream(stream);
stream.Free;
for i := 0 to slFile.Count-1 do
begin
oneLine := slFile.Strings[i];
//process the line
end;
现在,即使我没有获得任何锁定,我也会将整个文件加载到内存中。
是否有Assign
/ReadLn
的替代方案,我可以在其中逐行读取文件,而无需获取共享锁?
我不想直接进入Win32 CreateFile
/ReadFile
,并且必须处理分配缓冲区和检测CR
,LF
、CRLF
的。
我考虑过内存映射文件,但是如果整个文件不适合(映射)到虚拟内存中,并且必须一次映射文件的 View (片段),就会出现困难。开始变得丑陋。
我只想使用fmShareDenyNone
重置
!
最佳答案
对于最新的 Delphi 版本,您可以使用 TStreamReader
。使用您的文件流构建它,然后调用 its ReadLine
method (继承自TTextReader
)。
所有 Delphi 版本的一个选项是使用 Peter Below's StreamIO unit ,这将为您提供AssignStream
。它的工作方式与AssignFile
类似,但针对的是流而不是文件名。一旦您使用该函数将流与 TextFile
变量关联起来,您就可以像调用任何其他文件一样调用 ReadLn
以及其他 I/O 函数。
关于Delphi:使用 Reset/ReadLn 读取文本文件的替代方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2815839/