首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

急   内存映射文件有关问题

2012-02-10 
急!急!急!   内存映射文件问题我用内存映射文件加快读取大文件的速度,因文件很大,所以我分块映射,结果,读

急!急!急!   内存映射文件问题
我用内存映射文件加快读取大文件的速度,因文件很大,所以我分块映射,结果,读取的数字不正确,为什么?
代码如下:


  ......

  Qt::HANDLE hFile;
  Qt::HANDLE hMapFile;
  quint8 * lpwFileAddr;  
   
  hFile = CreateFile( fileName.utf16() , GENERIC_READ,0,NULL,
  OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);

  if ( hFile == INVALID_HANDLE_VALUE )
  {

  QMessageBox::warning( 0, "aaa1", QString::fromLocal8Bit("创建文件对象失败,错误代码") );
  return false;
  }


  hMapFile= CreateFileMapping(hFile,NULL, PAGE_READONLY,0,0,NULL);
  if ( hMapFile==NULL )
  {

  QMessageBox::warning( 0, "aaa2", QString::fromLocal8Bit("创建文件映射对象失败,错误代码") );
  return false;
  }
   

   
  SYSTEM_INFO sinf;
  GetSystemInfo(&sinf);
  DWORD dwAllocationGranularity = sinf.dwAllocationGranularity;

   
  quint64 offset=dwAllocationGranularity*1024;
  quint64 qwFileOffset=0;
  lpwFileAddr=(quint8 *)MapViewOfFile(hMapFile,FILE_MAP_READ, 0, qwFileOffset,offset);

  if ( lpwFileAddr == NULL )
  {
  QMessageBox::warning( 0, "aaa3", QString::fromLocal8Bit("创建文件映射对象失败,错误代码") );
  return false;
  }


  memcpy( &recNum, lpwFileAddr +3608, sizeof( Q_INT32 ) );
....


当我打印recNum时,发现它的值为16777216,这个值是不对的,应该是210,不知道为什么? 


[解决办法]
楼主估计是地址偏移搞错了,认真分析一边吧
[解决办法]
memcpy( &recNum, lpwFileAddr +3608, sizeof( Q_INT32 ) );
应该是这句话错了,从当前映射文件的3KB 开始复制,赋值的大小是sizeof( Q_INT32 ) ,给recNum,
所以计算的文件大小就是sizeof( Q_INT32 ),
 顺便问下楼主是怎么计算recNum?
[解决办法]
仅供参考

C/C++ code
#include <sys\stat.h>#include <io.h>#include <fcntl.h>#include <share.h>#include <stdlib.h>#include <stdio.h>#include <conio.h>#include <string.h>#define MAX_CLU_BYTES 65536FILE *fo;int fh;__int64 offs,offs1;__int64 rvi64;int rv,wrv;unsigned char buf[MAX_CLU_BYTES];char ofn[_MAX_PATH];void main(int argc,char **argv) {    if (argc<3) {        printf("Copy File Tail.\n");        printf("Usage:\n");        printf("    cft filename.ext offset_begin[-offset_end]\n");        printf("Copy filename.ext offset_begin[-offset_end] to offset_begin[-offset_end]-filename.ext\n");        printf("Note: Byte at offset_end is NOT included.\n");        printf("Example:\n");        printf("    cft abc.rar 12345\n");        printf("Copy abc.rar offset 12345-end to 12345-abc.rar\n");        printf("    cft abc.rar 123-12345\n");        printf("Copy abc.rar offset 123-12345 to 123-12345-abc.rar\n");        printf("    cft abc.rar 0xAB-0xCD\n");        printf("Copy abc.rar offset 0xAB-0xCD to 0xAB-0xCD-abc.rar\n");        return;    }    rv=sscanf(argv[2],"%I64i-%I64i",&offs,&offs1);    if (rv==0) {        printf("offset %s is not number\n",argv[2]);        return;    }    fh=_sopen(argv[1],_O_BINARY|_O_RDONLY|_O_RANDOM,_SH_DENYWR);    if (fh==-1) {        printf("_sopen %s errno=%d\n",argv[1],errno);        return;    }    if (rv==1) {        offs1=_filelengthi64(fh);        if (offs1==-1i64) {            printf("%I64=_filelengthi64 errno=%d\n",offs1,errno);            _close(fh);            return;        }    } else {//rv==2        if (offs1<offs) {            printf("%s offset_begin>offset_end error\n",argv[2]);            _close(fh);            return;        }    }    rvi64=_lseeki64(fh,offs,SEEK_SET);    if (rvi64!=offs) {        printf("%I64u=_lseeki64 %I64u errno=%d\n",rvi64,offs,errno);        _close(fh);        return;    }    sprintf(ofn,"%s-",argv[2]);    strcat(ofn,argv[1]);    fo=fopen(ofn,"wb");    if (fo==NULL) {        _close(fh);        printf("fopen %s error\n",ofn);        return;    }    cprintf("\n%I64u\r",offs);    while (1) {        rv=_read(fh,buf,(unsigned int)__min(offs1-offs,MAX_CLU_BYTES));        if (rv==0) break;//        if (rv<0) {            fclose(fo);            _close(fh);            printf("_read %s offset %I64u error\n",argv[1],offs);            return;        }        wrv=fwrite(buf,1,rv,fo);        if (wrv!=rv) {            fclose(fo);            _close(fh);            printf("fwrite %s error\n",ofn);            return;        } else {            offs+=rv;            cprintf("%I64u\r",offs);            if (offs>=offs1) break;//        }    }    fclose(fo);    _close(fh);    printf("Copy %s offset %s to %s OK.\n",argv[1],argv[2],ofn);} 


[解决办法]
读开始字节都不对,到后面肯定更不对啊;
先从简单的调试一下看看。

探讨

引用:
楼主可以读取开始字节,看看是否正确?


还是没有解决。
我想这样即使对了,也没有满足我的需要,
我要做的是:将segy文件(比较大)映射到内存,然后,抛去前面3608个字节,从3608读取,不知道为什么读的不对呢?
难道和lpwFileAddr定义的类型有关,该如何定义才正确呢?

[解决办法]
我试验了下面代码,是可行的,楼主参考一下:
首先在C盘下创建一个Mapping.txt里面输入1234567
C/C++ code
    HANDLE  hFile=CreateFile("c:\\mapping.txt",                                GENERIC_READ|GENERIC_WRITE,                                FILE_SHARE_READ|FILE_SHARE_WRITE,                                NULL,                                OPEN_EXISTING,                                FILE_ATTRIBUTE_NORMAL,                                NULL);    HANDLE hFilemap = CreateFileMapping(hFile,                                          NULL,                                          PAGE_READWRITE,                                          0,                                          100,     // 只是?辟100个                                          NULL);    LPVOID pVoid=MapViewOfFile(hFilemap,FILE_MAP_ALL_ACCESS,0,0,0);    char chDat[100];    memcpy(chDat, pVoid, 6);    // char *Buf=(char *)pVoid;    //     // Buf[0]='T';    CloseHandle(hFile);    CloseHandle(hFilemap);    UnmapViewOfFile(pVoid); 

热点排行