Tro*_*ian 3 delphi tstringlist filestream readfile delphi-xe2
我正在运行Delphi RAD Studio XE2.
我有一些非常大的文件,每个文件都包含大量的行.线条本身很小 - 只有3个标签分隔的双打.我想将文件加载到TStringList使用中,TStringList.LoadFromFile但这会引发大文件的异常.
对于200万行(约1GB)的文件,我得到了EIntOverflow例外.对于较大的文件(例如,2000万行和大约10GB),我得到了ERangeCheck例外.
我有32GB的RAM可供使用,我只是想加载这个文件并快速使用它.这里发生了什么,我有什么其他选择?我可以使用带有大缓冲区的文件流将此文件加载到TStringList中吗?如果是这样,请举一个例子.
Rem*_*eau 14
当Delphi在Delphi 2009中切换到Unicode时,该TStrings.LoadFromStream()方法(TStrings.LoadFromFile()内部调用)对于大型流/文件变得非常低效.
在内部,LoadFromStream()将整个文件作为a 读入内存TBytes,然后将其转换为UnicodeString使用TEncoding.GetString()(将字节解码为a TCharArray,将其复制到最终UnicodeString,然后释放数组),然后解析UnicodeString(当TBytes仍在内存中时)添加根据需要将子字符串放入列表中.
因此,在LoadFromStream()退出之前,内存中有四个文件数据副本 - 三个副本占用较差filesize * 3的内存字节(每个副本使用自己的连续内存块+一些MemoryMgr开销),一个副本用于解析子!当然,前三个副本在LoadFromStream()实际退出时被释放.但这解释了为什么在达到这一点之前你会遇到内存错误 - LoadFromStream()尝试使用3-4 GB内存来加载1GB文件,而RTL的内存管理器无法处理.
如果要将大文件的内容加载到a中TStringList,最好使用TStreamReader而不是LoadFromFile(). TStreamReader使用缓冲文件I/O方法以小块读取文件.只需ReadLine()在循环中调用其方法,Add()即将每一行调用到TStringList.例如:
//MyStringList.LoadFromFile(filename);
Reader := TStreamReader.Create(filename, true);
try
MyStringList.BeginUpdate;
try
MyStringList.Clear;
while not Reader.EndOfStream do
MyStringList.Add(Reader.ReadLine);
finally
MyStringList.EndUpdate;
end;
finally
Reader.Free;
end;
Run Code Online (Sandbox Code Playgroud)
也许有一天,LoadFromStream()可能会重新编写TStreamReader内部使用这样的东西.
| 归档时间: |
|
| 查看次数: |
5215 次 |
| 最近记录: |