急!求c++ builder 操作大文件的方法

liuyerits1234 2013-07-16 10:02:11
之前操作的txt档的大小一般不超过100M,所以直接用LoadFromFile的方法就可以直接读取文件,然后放入TStringList里再对数据进行处理分析,现在遇到了文件大小可能高达2GB这种,若用LoadFromFile的话就会出现Out of Memory

在网上搜寻了一下,知道有内存映射的方法,可是我还是疑问,内存映射到方法和分段的方法有什么区别,因为我开始是想先读一段,然后把这一段数据处理完,然后再读下一段,这样循环的,但是看了内存映射到方法思想好像和我想的不一样,我想请教一下内存映射读取了文件,如何对文件里的数据进行操作呢?

若是用分段的方法,那么又该如何分段呢?因为本身数据也是一块一块的
最好有使用内存映射或者分段的代码~

谢谢大家
...全文
169 点赞 收藏 14
写回复
14 条回复
liuyerits1234 2013年07月19日
問題解決了~ 謝謝妖哥~
回复 点赞
liuyerits1234 2013年07月18日
还是有个问题, 我定义的dwTmpBlockByte=128*0x10000 //4MB pMem->Write之后可以看到pMem的Count是0x800000, 但是listTmp->LoadFromStream(pMem)之后 listTmp的大小才0x15000左右,而且每次还不一样,这是为什么啊? 求指教啊~
回复 点赞
liuyerits1234 2013年07月18日
找到原因了,应该在listTmp->LoadFromStream(pMem)之前将指针pMem指向0的位置; 加上pMem->Position=0就可以了
回复 点赞
liuyerits1234 2013年07月18日
引用 9 楼 ccrun 的回复:
创建一个TMemoryStream对象,通过Write方法将需要分析的数据地址和长度写入,再用TStringList对象LoadFromStream就可以了。
谢谢妖哥~ 可是我目前还是有个小问题,我的代码如下: TMemoryStream *pMem=new TMemoryStream(); pMem->Position=0; HANDLE mvFile=MapViewOfFile(mapFile,File_MAP_READ,0,dwFileOffsetLow, dwTmpBlockByte); TStringList *listTmp= new TStringList; pMem->Write((char*)mvFile+dwFileOffsetLow,dwTmpBlockByte);//debug时可以看到这里是Ok的 listTmp->LoadFromStream(pMem);//问题就出在这里,我Load进来却发现listTmp的Count是为0的, 求指教这是为什么啊?
回复 点赞
ccrun.com 2013年07月18日
Position置零(相当于指针移到开始)是好多人容易忽略的一个问题。 pMem->Write以后,看看Size属性是多少?是否和写入的长度相同?
回复 点赞
ccrun.com 2013年07月17日
创建一个TMemoryStream对象,通过Write方法将需要分析的数据地址和长度写入,再用TStringList对象LoadFromStream就可以了。
回复 点赞
liuyerits1234 2013年07月17日
我的意思是我由MapViewOfFile知道了地址,那么我总不能一个char一个char的读取数据然后做判断吧? 有没有一段一段的读的方法?因为我是想把这些数据根据\r\n分行存入TStringList中去
回复 点赞
liuyerits1234 2013年07月17日
引用 6 楼 guanchaoyi 的回复:
char *buf= new char 只分配了一个字节的空间,你想要更多的空间,应该要指定,如: char *buf= new char[64*1024]。 另外内存映射操作文件,也不必再做memcpy了吧,可以通过MapViewOfFile指定映射的部分来处理;
谢谢你,的确可以不用Memcpy,但是我还有问题想请教一下, 用MapViewOfFile指的地址可以来操作数据对吗? 例如 LPVOID lpBuffer = MapViewOfFile(hMap, FILE_MAP_READ, 0, dwFileOffsetLow, dwTmpBlockByte) char cTmp=(char)(&lpBuffer);这样就可以获得起始地址的值了吗? 那么如果我想获得一段数据的,该如何做呢?
回复 点赞
关工 2013年07月17日
char *buf= new char 只分配了一个字节的空间,你想要更多的空间,应该要指定,如: char *buf= new char[64*1024]。 另外内存映射操作文件,也不必再做memcpy了吧,可以通过MapViewOfFile指定映射的部分来处理;
回复 点赞
liuyerits1234 2013年07月17日
char *buf= new char,这样给char分配空间是可以的吧?
回复 点赞
liuyerits1234 2013年07月17日
引用 3 楼 sololie 的回复:
http://blog.csdn.net/xmnathan/article/details/6072858
看了,目前我还是有一个问题, 我先用了LPVOID lpBuffer = ::MapViewOfFile(hMap, FILE_MAP_READ, 0, dwFileOffsetLow, dwTmpBlockByte)的参数,然后会有memcpy(buf,(char*)lpBuffer+dwFileOffsetLow,dwTmpBlockByte) 此时dwTmpBlockByte如果超过了0x10000的时候调试就会Hang住, memcpy应该不只能copy 64kb吧, 求帮助~ 求好心人~
回复 点赞
liuyerits1234 2013年07月16日
刚刚用了一下内存映射的方法,出现一个问题,麻烦有人指导一下 //处理大文件 HANDLE hOpenFile=CreateFile(sfile.t_str(),FILE_READ_EA,FILE_SHARE_READ,0,OPEN_EXISTING,0,0); if(hOpenFile!=Null) { ShowMessage("文件打开成功"); } else { ShowMessage("文件打开失败"); } int size=GetFileSize(hOpenFile,NULL); UnicodeString strtmp; ShowMessage(strtmp.sprintf(L"文件大小:%d",size)); HANDLE hFileMapping=CreateFileMapping(hOpenFile,NULL,PAGE_READONLY,0,0,NULL); if(hFileMapping!=0) { ShowMessage(“内存映射文件成功”); } else { ShowMessage(“内存映射文件失败”); } 问题就出在上面那句CreateFileMapping,得到了hFileMapping=NULL,那么内存映射失败了,这是怎么回事啊?
回复 点赞
liuyerits1234 2013年07月16日
没有人指教啊 我目前的想法是这样的 1.创建句柄:HANDLE hFile = CreateFile(sfile.t_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0); 2.获取文件大小:unsigned long mFileSize=GetFileSize(hFile,NULL); 3.创建文件映射:HANDLE hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY , NULL, (DWORD)(mFileSize&0xffffffff), NULL); 4.读取映射中的内存:LPVOID lpBuffer = ::MapViewOfFile(hMap, FILE_MAP_READ, NULL, NULL, mFileSize); 我想问一下MapViewOfFile中的参数dwFileOffsetHigh,dwFileOffsetLow设置为NULL有什么影响没?是根据什么设置这两个参数的,还有dwNumberOfBytesToMap这个参数我设置为文件的大小有没有关系啊,这样是否代表映射整个文件? 求高手,谢谢啦
回复 点赞
发动态
发帖子
Windows SDK/API
创建于2007-08-02

884

社区成员

8155

社区内容

C++ Builder Windows SDK/API
社区公告
暂无公告