如何用TMemoryStream打开超过1G的大文件?

时间:2021-03-20 17:21:27
我用TMemoryStream打开文件,几百M的能正常打开,但打开一个1.5G的大文件却提示“Out Of Memory”,怎么解决? 


TMemoryStream *baby=new TMemoryStream();
String FileName=Edit1->Text;
if(FileExists(FileName))
    {
        baby->LoadFromFile(FileName);
    }

19 个解决方案

#1


引用楼主 mylai911 的回复:
我用TMemoryStream打开文件,几百M的能正常打开,但打开一个1.5G的大文件却提示“Out Of Memory”,怎么解决?

C/C++ code
TMemoryStream*baby=new TMemoryStream();
String FileName=Edit1->Text;if(FileExists(FileName))
    {
        baby->LoadFromFile(FileName);
    }


你自己机器的内存多大?

#2


内存4G,这个应该和内存没关系,我估计是TMemoryStream的问题。

#3



建议使用文件映像
  CreateFile
  CreateFileMapping
  MapViewOfFile 

#4


你机器除了一些打开的软件,启动的服务,已经占有的内存后
还有多少内存可以使用?

#5


用SetSize 指定一下大小

#6


首先要看你的程序是否支持大内存,如果不支持的话,如果程序本身也占有相当大内存的话,那么由于受到1.99GB内存的限制,导致你的程序分配内存失败。其实一次性加载那么多数据到内存当中是没有任何必要性的,只会多余地占用系统的可用内存资源,就算你的程序能够在一秒钟处理完这么多数据,那么你分配这个内存也是需要相当多时间占用的。还不如小片小片地处理。

#7


顶......

以前我也犯了这个错误,后来发现一次性处理那么大一块本来就要花很多时间了,干脆一次20M,哈哈...

#8


引用 5 楼 zhouzhangkui 的回复:
用SetSize 指定一下大小


TFileStream里有这个方法么?

#9


引用 8 楼 silverpot 的回复:
引用 5 楼 zhouzhangkui 的回复:
用SetSize 指定一下大小


TFileStream里有这个方法么?

有的,TFileStream对应的是Windows API当中的SetFilePointer

#10


引用 9 楼 unsigned 的回复:
引用 8 楼 silverpot 的回复:
 引用 5 楼 zhouzhangkui 的回复:
 用SetSize 指定一下大小


 TFileStream里有这个方法么?

 有的,TFileStream对应的是Windows API当中的SetFilePointer


可是我在BCB6的帮助里没有找到TFileStream类有SetSize这个方法

#11


引用 10 楼 silverpot 的回复:
引用 9 楼 unsigned 的回复:
引用 8 楼 silverpot 的回复:
引用 5 楼 zhouzhangkui 的回复:
用SetSize 指定一下大小


TFileStream里有这个方法么?

有的,TFileStream对应的是Windows API当中的SetFilePointer


可是我在BCB6的帮助里没有找到TFileStream类有SetSize这个方法

不是有一个属性Size吗?直接给它赋值就OK了。

#12


Size和设置和Position的设置,对于TFileStream来说,都会调用SetFilePointer,所不同的是Size的设置会多调用一个SetEndOfFile.

#13


用64位版本windows,32位的应用程序大小不能超过2G

#14


建议使用文件映像 

#15


和TMemoryStream没关系。32位程序的内存地址只有4G,其中应用程序可以访问的默认只有2G。操作系统再把DLL基址一调整,可用的连续内存地址就只有几百兆了。
解决的办法是用磁盘文件作缓冲,一次只映射少量数据到内存,或者升级到64位的操作系统并且使用64位的编译器,重写程序使得程序和64位操作系统兼容。

#16


引用 15 楼 jiangsheng 的回复:
和TMemoryStream没关系。32位程序的内存地址只有4G,其中应用程序可以访问的默认只有2G。操作系统再把DLL基址一调整,可用的连续内存地址就只有几百兆了。
 解决的办法是用磁盘文件作缓冲,一次只映射少量数据到内存,或者升级到64位的操作系统并且使用64位的编译器,重写程序使得程序和64位操作系统兼容。

正解在这里
换个方法,每次处理一块不就好了

#17


这几天正在关注windows内存管理的问题.默认情况下在Win32平台,一个应用程序最多只能管理到1.6GB内存,而Load进1.5GB的数据,需要的内存会超过1.6GB(程序本身还有消耗,加上其它),所以楼主加载失败是正常的。如果系统有足够的内存,建议对程序启用LARGEADDRESSAWARE,方法: https://forums.embarcadero.com/thread.jspa?threadID=24090
如果希望管理超过2GB内存(在Win32平台下可以达到2.5GB),那么对操作系统的boot选项(boot.ini)添加“/3GB"参数。

#18


学习下。

#19


引用 17 楼 unsigned 的回复:
这几天正在关注windows内存管理的问题.默认情况下在Win32平台,一个应用程序最多只能管理到1.6GB内存,而Load进1.5GB的数据,需要的内存会超过1.6GB(程序本身还有消耗,加上其它),所以楼主加载失败是正常的。如果系统有足够的内存,建议对程序启用LARGEADDRESSAWARE,方法:https://forums.embarcadero.com/thread.jspa?threadID=24090
如果希望管理超过2GB内存(在Win32平台下可以达到2.5GB),那么对操作系统的boot选项(boot.ini)添加“/3GB"参数。


17楼正解, 不过正常情况下是 1.7G 而不是1.6G
这不光是window系统的问题,在Linux系统也是一样。
看看4G内存分布就情况了

#1


引用楼主 mylai911 的回复:
我用TMemoryStream打开文件,几百M的能正常打开,但打开一个1.5G的大文件却提示“Out Of Memory”,怎么解决?

C/C++ code
TMemoryStream*baby=new TMemoryStream();
String FileName=Edit1->Text;if(FileExists(FileName))
    {
        baby->LoadFromFile(FileName);
    }


你自己机器的内存多大?

#2


内存4G,这个应该和内存没关系,我估计是TMemoryStream的问题。

#3



建议使用文件映像
  CreateFile
  CreateFileMapping
  MapViewOfFile 

#4


你机器除了一些打开的软件,启动的服务,已经占有的内存后
还有多少内存可以使用?

#5


用SetSize 指定一下大小

#6


首先要看你的程序是否支持大内存,如果不支持的话,如果程序本身也占有相当大内存的话,那么由于受到1.99GB内存的限制,导致你的程序分配内存失败。其实一次性加载那么多数据到内存当中是没有任何必要性的,只会多余地占用系统的可用内存资源,就算你的程序能够在一秒钟处理完这么多数据,那么你分配这个内存也是需要相当多时间占用的。还不如小片小片地处理。

#7


顶......

以前我也犯了这个错误,后来发现一次性处理那么大一块本来就要花很多时间了,干脆一次20M,哈哈...

#8


引用 5 楼 zhouzhangkui 的回复:
用SetSize 指定一下大小


TFileStream里有这个方法么?

#9


引用 8 楼 silverpot 的回复:
引用 5 楼 zhouzhangkui 的回复:
用SetSize 指定一下大小


TFileStream里有这个方法么?

有的,TFileStream对应的是Windows API当中的SetFilePointer

#10


引用 9 楼 unsigned 的回复:
引用 8 楼 silverpot 的回复:
 引用 5 楼 zhouzhangkui 的回复:
 用SetSize 指定一下大小


 TFileStream里有这个方法么?

 有的,TFileStream对应的是Windows API当中的SetFilePointer


可是我在BCB6的帮助里没有找到TFileStream类有SetSize这个方法

#11


引用 10 楼 silverpot 的回复:
引用 9 楼 unsigned 的回复:
引用 8 楼 silverpot 的回复:
引用 5 楼 zhouzhangkui 的回复:
用SetSize 指定一下大小


TFileStream里有这个方法么?

有的,TFileStream对应的是Windows API当中的SetFilePointer


可是我在BCB6的帮助里没有找到TFileStream类有SetSize这个方法

不是有一个属性Size吗?直接给它赋值就OK了。

#12


Size和设置和Position的设置,对于TFileStream来说,都会调用SetFilePointer,所不同的是Size的设置会多调用一个SetEndOfFile.

#13


用64位版本windows,32位的应用程序大小不能超过2G

#14


建议使用文件映像 

#15


和TMemoryStream没关系。32位程序的内存地址只有4G,其中应用程序可以访问的默认只有2G。操作系统再把DLL基址一调整,可用的连续内存地址就只有几百兆了。
解决的办法是用磁盘文件作缓冲,一次只映射少量数据到内存,或者升级到64位的操作系统并且使用64位的编译器,重写程序使得程序和64位操作系统兼容。

#16


引用 15 楼 jiangsheng 的回复:
和TMemoryStream没关系。32位程序的内存地址只有4G,其中应用程序可以访问的默认只有2G。操作系统再把DLL基址一调整,可用的连续内存地址就只有几百兆了。
 解决的办法是用磁盘文件作缓冲,一次只映射少量数据到内存,或者升级到64位的操作系统并且使用64位的编译器,重写程序使得程序和64位操作系统兼容。

正解在这里
换个方法,每次处理一块不就好了

#17


这几天正在关注windows内存管理的问题.默认情况下在Win32平台,一个应用程序最多只能管理到1.6GB内存,而Load进1.5GB的数据,需要的内存会超过1.6GB(程序本身还有消耗,加上其它),所以楼主加载失败是正常的。如果系统有足够的内存,建议对程序启用LARGEADDRESSAWARE,方法: https://forums.embarcadero.com/thread.jspa?threadID=24090
如果希望管理超过2GB内存(在Win32平台下可以达到2.5GB),那么对操作系统的boot选项(boot.ini)添加“/3GB"参数。

#18


学习下。

#19


引用 17 楼 unsigned 的回复:
这几天正在关注windows内存管理的问题.默认情况下在Win32平台,一个应用程序最多只能管理到1.6GB内存,而Load进1.5GB的数据,需要的内存会超过1.6GB(程序本身还有消耗,加上其它),所以楼主加载失败是正常的。如果系统有足够的内存,建议对程序启用LARGEADDRESSAWARE,方法:https://forums.embarcadero.com/thread.jspa?threadID=24090
如果希望管理超过2GB内存(在Win32平台下可以达到2.5GB),那么对操作系统的boot选项(boot.ini)添加“/3GB"参数。


17楼正解, 不过正常情况下是 1.7G 而不是1.6G
这不光是window系统的问题,在Linux系统也是一样。
看看4G内存分布就情况了

#20