精华内容
下载资源
问答
  • Java中用内存映射处理大文件.pdf
  • 下面小编就为大家带来一篇Java中用内存映射处理大文件的实现代码。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • Java中用内存映射处理大文件

    千次阅读 2018-05-29 14:41:10
    工作中有一次发现,利用FileInputStream处理文件时很慢,于是想有没有读取文件时比较快的方法,网上有说利用内存映射处理大文件,下面我们一起看一组对比试验:package test.api; import java.io.*; import java....

            工作中有一次发现,利用FileInputStream处理文件时很慢,于是想有没有读取大文件时比较快的方法,网上有说利用内存映射处理大文件,下面我们一起看一组对比试验:

    package test.api;
    
    import java.io.*;
    import java.nio.MappedByteBuffer;
    import java.nio.channels.FileChannel;
    
    public class GCTest {
    
    
        public static void main(String[] args) {
            try {
                FileInputStream fis=new FileInputStream("D:\\res.txt");
                int sum=0;
                int n;
                long t1=System.currentTimeMillis();
                try {
                    while((n=fis.read())>=0){
                        sum+=n;
                    }
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                long t=System.currentTimeMillis()-t1;
                System.out.println("sum:"+sum+"  time:"+t);
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    
            try {
                FileInputStream fis=new FileInputStream("D:\\res.txt");
                BufferedInputStream bis=new BufferedInputStream(fis);
                int sum=0;
                int n;
                long t1=System.currentTimeMillis();
                try {
                    while((n=bis.read())>=0){
                        sum+=n;
                    }
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                long t=System.currentTimeMillis()-t1;
                System.out.println("sum:"+sum+"  time:"+t);
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    
            MappedByteBuffer buffer=null;
            try {
                buffer=new RandomAccessFile("D:\\res.txt","rw").getChannel().map(FileChannel.MapMode.READ_WRITE, 0, 151552);
                int sum=0;
                int n;
                long t1=System.currentTimeMillis();
                for(int i=0;i<151552;i++){
                    n=0x000000ff&buffer.get(i);
                    sum+=n;
                }
                long t=System.currentTimeMillis()-t1;
                System.out.println("sum:"+sum+"  time:"+t);
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    
        }
    
    }

    测试文件为一个大小为151552KB,测试结果为:

    sum:13430346  time:186
    sum:13430346  time:13

    sum:13430346  time:4

    说明数据读取无误,下面删除数据处理部分

    package test.api;
    
    import java.io.*;
    import java.nio.MappedByteBuffer;
    import java.nio.channels.FileChannel;
    
    public class GCTest {
    
    
        public static void main(String[] args) {
            try {
                FileInputStream fis=new FileInputStream("D:\\res.txt");
                int sum=0;
                int n;
                long t1=System.currentTimeMillis();
                try {
                    while((n=fis.read())>=0){
                        //sum+=n;
                    }
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                long t=System.currentTimeMillis()-t1;
                System.out.println("sum:"+sum+"  time:"+t);
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    
            try {
                FileInputStream fis=new FileInputStream("D:\\res.txt");
                BufferedInputStream bis=new BufferedInputStream(fis);
                int sum=0;
                int n;
                long t1=System.currentTimeMillis();
                try {
                    while((n=bis.read())>=0){
                        //sum+=n;
                    }
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                long t=System.currentTimeMillis()-t1;
                System.out.println("sum:"+sum+"  time:"+t);
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    
            MappedByteBuffer buffer=null;
            try {
                buffer=new RandomAccessFile("D:\\res.txt","rw").getChannel().map(FileChannel.MapMode.READ_WRITE, 0, 151552);
                int sum=0;
                int n;
                long t1=System.currentTimeMillis();
                for(int i=0;i<151552;i++){
    //                n=0x000000ff&buffer.get(i);
    //                sum+=n;
                }
                long t=System.currentTimeMillis()-t1;
                System.out.println("sum:"+sum+"  time:"+t);
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    
        }
    
    }

    处理结果:

    sum:0  time:151
    sum:0  time:7

    sum:0  time:1

    由此可见,将文件部分或者全部映射到内存后进行读写,速度将提高很多。

    展开全文
  • 文件操作是应用程序最为基本的功能之一,Win32 API和MFC均提供有支持文件处 理的函数和类...目前,对于上述这种大文件的操作一般是以内存映射文件的方式来加以处理的,本文下面将针对这种Windows核心编程技术展开讨论。
  • 分块内存映射处理大文件-例子

    千次阅读 2013-04-18 16:06:34
    app=2&via=QZ.HashRefresh&pos=1363445766 ...• 系统使用内存映射文件,以便加载和执行. exe和DLL文件。这可以大大节省页文件空间和应用程序启动运行所需的时间。 • 可以使用内存映射文件来访问磁盘上的数

    参考 :http://user.qzone.qq.com/382164370/infocenter#!app=2&via=QZ.HashRefresh&pos=1363445766

    内存映射文件可以用于3个不同的目的

    • 系统使用内存映射文件,以便加载和执行. exe和DLL文件。这可以大大节省页文件空间和应用程序启动运行所需的时间。

    • 可以使用内存映射文件来访问磁盘上的数据文件。这使你可以不必对文件执行I/O操作,并且可以不必对文件内容进行缓存

    • 可以使用内存映射文件,使同一台计算机上运行的多个进程能够相互之间共享数据。Windows确实提供了其他一些方法,以便在进程之间进行数据通信,但是这些方法都是使用内存映射文件来实现的,这使得内存映射文件成为单个计算机上的多个进程互相进行通信的最有效的方法。

    使用内存映射数据文件 

    若要使用内存映射文件,必须执行下列操作步骤:

    1) 创建或打开一个文件内核对象,该对象用于标识磁盘上你想用作内存映射文件的文件。

    2) 创建一个文件映射内核对象,告诉系统该文件的大小和你打算如何访问该文件。

    3) 让系统将文件映射对象的全部或一部分映射到你的进程地址空间中。

    当完成对内存映射文件的使用时,必须执行下面这些步骤将它清除:

    1) 告诉系统从你的进程的地址空间中撤消文件映射内核对象的映像。

    2) 关闭文件映射内核对象。

    3) 关闭文件内核对象。


          文件操作是应用程序最为基本的功能之一,Win32 API和MFC均提供有支持文件处理的函数和类,常用的有Win32 API的CreateFile()、WriteFile()、ReadFile()和MFC提供的CFile类等。一般来说,以上这些函数可以满足大多数场合的要求,但是对于某些特殊应用领域所需要的动辄几十GB、几百GB、乃至几TB的海量存储,再以通常的文件处理方法进行处理显然是行不通的。所以可以使用内存文件映射来处理数据,网上也有铺天盖地的文章,但是映射大文件的时候又往往会出错,需要进行文件分块内存映射,这里就是这样的一个例子,教你如何把文件分块映射到内存。


    //
    // 该函数用于读取从CCD摄像头采集来的RAW视频数据当中的某一帧图像,
    // RAW视频前596字节为头部信息,可以从其中读出视频总的帧数,
    // 帧格式为1024*576*8
    /* 
    参数:
    	pszPath:文件名
    	dwFrame: 要读取第几帧,默认读取第2帧
    */
    BOOL  MyFreeImage::LoadXRFrames(TCHAR *pszPath, DWORD dwFrame/* = 2*/ )
    {
    
    	// get the frames of X-Ray frames
    	BOOL bLoop = TRUE;
    	int	i;
    	int width = 1024;
    	int height = 576;
    	int bitcount = 8;			//1, 4, 8, 24, 32
    
    	//
    	//Build bitmap header
    	BITMAPFILEHEADER bitmapFileHeader; 
    	BITMAPINFOHEADER bitmapInfoHeader; 
    	BYTE			 rgbquad[4];			// RGBQUAD
    	int				 index = 0;
    
    	DWORD widthbytes = ((bitcount*width + 31)/32)*4;		//每行都是4的倍数  DWORD的倍数  这里是 576-
    	TRACE1("widthbytes=%d\n", widthbytes);
    
    	switch(bitcount) { 
    	case 1: 
    		index = 2; 
    		bitmapFileHeader.bfOffBits = (DWORD)(sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 2*4); 
    		break; 
    	case 4: 
    		index = 16; 
    		bitmapFileHeader.bfOffBits = (DWORD)(sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 16*4); 
    		break; 
    	case 8: 
    		index = 256; 
    		bitmapFileHeader.bfOffBits = (DWORD)(sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 256*sizeof(RGBQUAD)); 
    		break; 
    	case 24: 
    	case 32: 
    		index = 0; 
    		bitmapFileHeader.bfOffBits = (DWORD)(sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)); 
    		break; 
    	default:
    		break;
    	} 
    
    	//构造Bitmap文件头BITMAPFILEHEADER 
    	bitmapFileHeader.bfType = 0x4d42;    // 很重要的标志位  BM 标识
    	bitmapFileHeader.bfSize = (DWORD)(bitmapFileHeader.bfOffBits + height * widthbytes);		//bmp文件长度  
    	bitmapFileHeader.bfReserved1 = 0; 
    	bitmapFileHeader.bfReserved2 = 0; 
    
    	//构造Bitmap文件信息头BITMAPINFOHEADER 
    	bitmapInfoHeader.biSize = sizeof(BITMAPINFOHEADER); 
    	bitmapInfoHeader.biWidth = width; 
    	bitmapInfoHeader.biHeight = height; 
    	bitmapInfoHeader.biPlanes = 1; 
    	bitmapInfoHeader.biBitCount = bitcount;
    	bitmapInfoHeader.biCompression = BI_RGB;  // 未压缩
    	bitmapInfoHeader.biSizeImage = height * widthbytes; 
    	bitmapInfoHeader.biXPelsPerMeter = 3780; 
    	bitmapInfoHeader.biYPelsPerMeter = 3780; 
    	bitmapInfoHeader.biClrUsed = 0; 
    	bitmapInfoHeader.biClrImportant = 0; 
    
    	//创建BMP内存映像,写入位图头部
    	BYTE *pMyBmp = new BYTE[bitmapFileHeader.bfSize];		// 我的位图pMyBmp
    	BYTE *curr = pMyBmp;									// curr指针指示pMyBmp的位置
    	memset(curr, 0, bitmapFileHeader.bfSize); 
    
    	//写入头信息 
    	memcpy(curr, &bitmapFileHeader,sizeof(BITMAPFILEHEADER));
    	curr = pMyBmp + sizeof(BITMAPFILEHEADER); 
    	memcpy(curr, &bitmapInfoHeader,sizeof(BITMAPINFOHEADER)); 
    	curr += sizeof(BITMAPINFOHEADER);
    
    	//构造调色板 , 当像素大于8位时,就没有调色板了。
    	if(bitcount == 8) 
    	{
    		rgbquad[3] = 0;										//rgbReserved
    		for(i = 0; i < index; i++) 
    		{ 
    			rgbquad[0] = rgbquad[1] = rgbquad[2] = i; 
    			memcpy(curr, rgbquad, sizeof(RGBQUAD)); 
    			curr += sizeof(RGBQUAD); 
    		} 
    	}else if(bitcount == 1) 
    	{ 
    		rgbquad[3] = 0;										//rgbReserved
    		for(i = 0; i < index; i++) 
    		{ 
    			rgbquad[0] = rgbquad[1] = rgbquad[2] = (256 - i)%256; 
    			memcpy(curr, rgbquad, sizeof(RGBQUAD)); 
    			curr += sizeof(RGBQUAD); 
    		} 
    	} 
    
    	//
    	// 文件映射,从文件中查找图像的数据
    	//Open the real file on the file system
    	HANDLE hFile = CreateFile(pszPath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    	if (hFile == INVALID_HANDLE_VALUE)
    	{
    		DWORD dwError = GetLastError();
    		ATLTRACE(_T("MapFile, Failed in call to CreateFile, Error:%d\n"), dwError);
    		SetLastError(dwError);
    		bLoop = FALSE;
    		return FALSE;
    	}
    
    	//Create the file mapping object
    	HANDLE hMapping = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, NULL);
    	if (hMapping == NULL)
    	{
    		DWORD dwError = GetLastError();
    		ATLTRACE(_T("MapFile, Failed in call to CreateFileMapping, Error:%d\n"), dwError);
    
    		// Close handle
    		if (hFile != INVALID_HANDLE_VALUE)
    		{
    			CloseHandle(hFile);
    			hFile = INVALID_HANDLE_VALUE;
    		}
    
    		SetLastError(dwError);
    		bLoop = FALSE;
    		return FALSE;
    	}
    
    	// Retrieve allocation  granularity
    	SYSTEM_INFO sinf;
    	GetSystemInfo(&sinf);
    	DWORD dwAllocationGranularity = sinf.dwAllocationGranularity;
    
    	// Retrieve file size
    	// Retrieve file size
    	DWORD dwFileSizeHigh;
    	__int64 qwFileSize = GetFileSize(hFile, &dwFileSizeHigh);
    	qwFileSize |= (((__int64)dwFileSizeHigh) << 32);
    
    	CloseHandle(hFile);
    
    	// Read Image
    	__int64 qwFileOffset = 0;									// 偏移地址
    	DWORD   dwBytesInBlock = 0,									// 映射的块大小
    			dwStandardBlock = 100* dwAllocationGranularity ;	// 标准块大小
    	DWORD   dwFrameSize = height*width;					        // 计算一帧图像的数据量,不包括头部信息
    	DWORD   dwCurrentFrame = 1;
    
    	dwBytesInBlock = dwStandardBlock;
    	if (qwFileSize < dwStandardBlock)
    		dwBytesInBlock  = (DWORD)qwFileSize;
    
    	//Map the view  
    	LPVOID lpData = MapViewOfFile(hMapping,  FILE_MAP_ALL_ACCESS, 
    		static_cast<DWORD>((qwFileOffset & 0xFFFFFFFF00000000) >> 32), static_cast<DWORD>(qwFileOffset & 0xFFFFFFFF), dwBytesInBlock);
    	if (lpData == NULL)
    	{
    		DWORD dwError = GetLastError();
    		ATLTRACE(_T("MapFile, Failed in call to MapViewOfFile, Error:%d\n"), dwError);
    
    		// Close Handle
    		if (hMapping != NULL)
    		{
    			CloseHandle(hMapping);
    			hMapping = NULL;
    		}
    		SetLastError(dwError);
    		bLoop = FALSE;
    		return FALSE;
    	}
    
    
    	BYTE  *lpBits = (BYTE *)lpData;
    	BYTE  *curr1, *curr2, *lpEnd;
    	curr1 = lpBits;							// seek to start
    	curr2 = lpBits + 596;					// seek to first frame
    	lpEnd = lpBits + dwBytesInBlock;		// seek to end
    
    	// Read video infomation
    	KMemDataStream streamData( curr1, dwBytesInBlock);
    	ReadXRHeader(streamData);
    
    	while(bLoop)
    	{
    		DWORD dwTmp = lpEnd - curr2;		//内存缓冲剩余的字节
    		if ( dwTmp >= dwFrameSize )	
    		{
    			if(dwCurrentFrame == dwFrame)
    			{
    				memcpy(curr, curr2, dwFrameSize);
    				bLoop = FALSE;
    			}
    			curr2 += dwFrameSize;
    		}else		//内存中不够一帧数据
    		{
    			DWORD dwTmp2 = dwFrameSize - dwTmp;			// 一副完整的帧还需要dwTmp2字节
    
    			if (dwCurrentFrame == dwFrame)
    			{
    				memcpy(curr, curr2, dwTmp);
    				curr += dwTmp;
    			}
    
                            
    			//1、首先计算文件的偏移位置
                            qwFileOffset += dwBytesInBlock;
    //2、 检查还可以映射多少字节的东东到内存里面if ( qwFileSize - qwFileOffset < dwStandardBlock)dwBytesInBlock = (DWORD)(qwFileSize - qwFileOffset);//3、重新映射文件UnmapViewOfFile(lpData);lpData = MapViewOfFile(hMapping, FILE_MAP_ALL_ACCESS, static_cast<DWORD>((qwFileOffset & 0xFFFFFFFF00000000) >> 32), static_cast<DWORD>(qwFileOffset & 0xFFFFFFFF), dwBytesInBlock);if (lpData == NULL) // 一定要检查,不然可能内存映射失败{DWORD dwError = GetLastError();ATLTRACE(_T("MapFile, Failed in call to MapViewOfFile, Error:%d\n"), dwError);SetLastError(dwError);bLoop = FALSE;break;}curr2 = lpBits = (BYTE *)lpData;lpEnd = lpBits + dwBytesInBlock; // seek to endif (dwCurrentFrame == dwFrame){memcpy(curr, curr2, dwTmp2);bLoop = FALSE;}curr2 += dwTmp2;}dwCurrentFrame++;if (dwCurrentFrame > ((LPKINFO)m_VideoInfoHeader)->frames ) // 到达文件末尾{bLoop = FALSE;}}//将内存流 pMyBmp 转为bitmapKMemDataStream stream(pMyBmp, bitmapFileHeader.bfSize, true);if(!LoadFromMemory(FIF_BMP, stream))return FALSE;//if (lpData != NULL){//FlushViewOfFile(lpData, 0);UnmapViewOfFile(lpData);lpData = NULL;}//remove the file mappingif (hMapping != NULL){CloseHandle(hMapping);hMapping = NULL;}return TRUE;}
    
    

    展开全文
  • 今天工作中遇到一个处理大文件的问题,开始以为是MapViewOfFile在读取文件时出了问题,所以稍微研究了下内存映射的问题。 最后分析虽然不是这方面的问题,但还是有点收获的。(网上搜集的资料整理) ...

    今天工作中遇到一个处理大文件的问题,开始以为是MapViewOfFile在读取文件时出了问题,所以稍微研究了下内存映射的问题。

    最后分析虽然不是这方面的问题,但还是有点收获的。(网上搜集的资料整理)

    http://www.yesky.com/405/1756405.shtml

    http://blog.csdn.net/dsg333/article/details/8260178

    /

    1、为何文件映射适合处理大文件?

    文件操作是应用程序最为基本的功能之一,Win32 API和MFC均提供有支持文件处理的函数和类,常用的有Win32 API的CreateFile()、WriteFile()、ReadFile()和MFC提供的CFile类等。一般来说,以上这些函数可以满足大多数 场合的要求,但是对于某些特殊应用领域所需要的动辄几十GB、几百GB、乃至几TB的海量存储,再以通常的文件处理方法进行处理显然是行不通的。目前,对 于上述这种大文件的操作一般是以内存映射文件的方式来加以处理的。

    内存文件映射是Windows的一种内存管理方法,提供了一个统一的内存管理特征,使应用程序可以通过内存指针对磁盘上的文件进行访问,其过程就如同对 加载了文件的内存的访问。通过文件映射这种使磁盘文件的全部或部分内容与进程虚拟地址空间的某个区域建立映射关联的能力,可以直接对被映射的文件进行访 问,而不必执行文件I/O操作也无需对文件内容进行缓冲处理。 内存文件映射的这种特性是非常适合于用来管理大尺寸文件的。

    2、内存映射原理

    网上这篇文章讲得很清晰:http://blog.csdn.net/mg0832058/article/details/5890688

    3、MapViewOfFile参数说明

    MapViewOfFile(
    __in HANDLE hFileMappingObject,              //共享文件对象
    __in DWORD dwDesiredAccess,                 //文件共享属性
    __in DWORD dwFileOffsetHigh,                   //文件共享区的偏移地址高32位
    __in DWORD dwFileOffsetLow,                    //文件共享区的偏移地址低32位
    __in SIZE_T dwNumberOfBytesToMap       //共享数据长度
    );

    内存文件映函数的第一个参数为CreateFileMapping()所返回的内存映射文件对象句柄,第二个参数指定了对文件映像的访问类型,可能取值有 FILE_MAP_WRITE、FILE_MAP_READ、FILE_MAP_ALL_ACCESS和FILE_MAP_COPY等几种,具体的设置要 根据文件映射对象允许的保护模式而定。根据前面代码的设置,这里应该使用FILE_MAP_ALL_ACCESS参数。这种机制为对象的创建者提供了对映 射此对象的方式进行控制的能力。

    接下来的2个参数分别指定了内存映射文件的64位偏移地址的低32位和高32位地址,该地址是从内存映射文件头位置到映像开始位置的距离。最后的参数指定了视图的大小,如果设置为0,前面的偏移地址将被忽略,系统将会把整个文件映射为一个映像。

    MapViewOfFile()如果成功执行,将返回一个指向文件映像在进程的地址空间中的起始地址的指针。如果失败,则返回NULL。在进程中,可以为 同一个文件映射对象创建多个文件映像,这些映像可以在系统中共存和重叠,也可以与对应的文件映射对象大小不相一致,但不能大于文件映射对象的大小。

    4、VirtualProtect()函数说明

    BOOL WINAPI VirtualProtect(
      __in   LPVOID lpAddress,
      __in   SIZE_T dwSize,
      __in   DWORD flNewProtect,
      __out  PDWORD lpflOldProtect
    );
    我们在调用MapViewOfFile之后,根据需求可以调用该函数,此函数可以改变调用进程虚拟地址空间中已提交页上的一段内存的保护属性。
    第 1 个参数 lpAddress 是输入参数,是虚拟内存基地址。
    第 2 个参数 dwSize 是输入参数,表示要改变内存区域的大小。
    第 3 个参数 flNewProtect 是输入参数,给出了要设置的新的保护属性,可以为 PAGE_READONLY, PAGE_EXECUTE,PAGE_EXECUTE_READ 等。
    第 4 个参数 lpflOldProtect 是输出参数,指向保存原保护属性值(DWORD),当其为 NULL 或 指向一个错误的变量时函数都将失败。

    5、文件分块处理

    文件不太大的话,调用MapViewOfFile参数可按默认处理:

    lpFileBase = (LPBYTE)MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, 0);
    if(NULL == lpFileBase)
    {
    	CloseHandle(hFileMapping);
    	CloseHandle(hFile);
    	return;
    }

    文件比较大,需分块处理时,代码如下:

    // 创建文件对象
    HANDLE hFile = ::CreateFile(strFile, GENERIC_READ,FILE_SHARE_READ, NULL, 
       OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, NULL);
    if (hFile == INVALID_HANDLE_VALUE)
    {
       TRACE("创建文件对象失败,错误代码:%d\r\n", GetLastError());
       return;
    }
    // 创建文件映射对象
    HANDLE hFileMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
    if (hFileMap == NULL)
    {
       TRACE("创建文件映射对象失败,错误代码:%d\r\n", GetLastError());  
       return;
    }
    // 得到系统分配粒度
    SYSTEM_INFO SysInfo;
    GetSystemInfo(&SysInfo);
    DWORD dwGran = SysInfo.dwAllocationGranularity;
    // 得到文件尺寸
    DWORD dwFileSizeHigh;
    __int64 qwFileSize = GetFileSize(hFile, &dwFileSizeHigh);
    qwFileSize |= (((__int64)dwFileSizeHigh) << 32);///MSDN
    
    // 偏移地址 
    __int64 qwFileOffset = 0;
    __int64 T_newmap = 900 * dwGran;
    // 块大小
    DWORD dwBlockBytes = 1000 * dwGran;//文件数据分段大小
    if (qwFileSize - qwFileOffset < dwBlockBytes)
       dwBlockBytes = (DWORD)qwFileSize;
    
    // 映射视图
    char *lpbMapAddress = (char *)MapViewOfFile(hFileMap,FILE_MAP_READ,
       (DWORD)(qwFileOffset >> 32), (DWORD)(qwFileOffset & 0xFFFFFFFF),dwBlockBytes);
    if (lpbMapAddress == NULL)
    {
       TRACE("映射文件映射失败,错误代码:%d ", GetLastError());
       return;
    } 
    // 关闭文件对象
    CloseHandle(hFile); 
    ///读文件数据
    while(qwFileOffset < qwFileSize)
    {
       /********************            读文件             ***************************/  
       //read_eh(&lpbMapAddress)读取已映射到内存的数据,并将文件指针作相应后移(lpbMapAddress++),返回指针偏移量
       qwFileOffset = qwFileOffset + read_eh(&lpbMapAddress); //修改偏移量
       if (qwFileOffset > T_newmap)
       {//当数据读到90%时,为防数据溢出,需要映射在其后的数据 T_newmap
        UnmapViewOfFile(lpbMapAddress);//释放当前映射
        if ((DWORD)(qwFileSize - T_newmap) < dwBlockBytes)
        dwBlockBytes = (DWORD)(qwFileSize - T_newmap);
        lpbMapAddress = (char *)MapViewOfFile(hFileMap,FILE_MAP_READ,
        (DWORD)(T_newmap >> 32), (DWORD)(T_newmap & 0xFFFFFFFF),dwBlockBytes);
        // 修正参数
        lpbMapAddress = lpbMapAddress + qwFileOffset - T_newmap;
        T_newmap =T_newmap + 900 * dwGran;
        if (lpbMapAddress == NULL)
        {
         TRACE("映射文件映射失败,错误代码:%d ", GetLastError());
         return;
        } 
       }
    }
    //释放最后数据块映射
    UnmapViewOfFile(lpbMapAddress);
    // 关闭文件映射对象句柄
    CloseHandle(hFileMap); 

    代码的意思是一次每次映射dwBlockBytes个字节,即1000*64KB(只有在最后次映射不够这么多时才映射 qwFileSize - T_newmap个字节),虽说每次映射1000*64KB字节,但当读取超过900*64KB个字节时,就进行下一次映射, 下一次映射就从上次的900*64KB处开始,映射1000*64KB。所以每次的偏移量就是900*64KB的倍数,也就是用t_newmap来偏移。

    展开全文
  • visual c++ vc使用内存映射文件mapping file处理大文件
  • 主要介绍了Java内存映射 大文件轻松处理,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • VC++中使用内存映射文件处理大文件.pdf
  • 采用内存映射文件的方法处理大文件,快速有效的文件处理方式。
  • 文件操作是应用程序最为基本的功能之一,Win32 API和MFC均提供有支持文件处理的函数和类...目前,对于上述这种大文件的操作一般是以内存映射文件的方式来加以处理的,本文下面将针对这种Windows核心编程技术展开讨论。
  • 文件操作是应用程序最为基本的功能之一,Win32 API和MFC均提供有支持文件处理的函数和类...目前,对于上述这种大文件的操作一般是以内存映射文件的方式来加以处理的,本文下面将针对这种Windows核心编程技术展开讨论。
  • 使用内存映射文件处理大文件示例

    千次阅读 2018-01-05 15:40:38
    其实,我们在把内存映射文件映射到进程的地址空间时,可以映射一部分,通过一个循环,把整个文件处理完 下面我举个例子 #include #include #include using namespace std; __int64 Count0s(); int main() { ...

    前面我们讲过内存映射文件的使用,但是,如果文件大小超过内存大小那怎么办呢
    其实,我们在把内存映射文件映射到进程的地址空间时,可以映射一部分,通过一个循环,把整个文件处理完

    下面我举个例子

    #include <windows.h>
    #include <iostream>
    #include <stdio.h>
    using namespace std;
    __int64 Count0s();
    int main()
    {
        __int64 co=Count0s();
        //cout<<co<<endl;
        printf("%I64u",co);
        system("pause");
        return 0;
    }
    
    __int64 Count0s()
    {
        SYSTEM_INFO si;
        GetSystemInfo(&si);
        //打开数据文件
        HANDLE hFile=CreateFile("FuncMan.dat",GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_FLAG_SEQUENTIAL_SCAN,NULL);
        if(hFile==INVALID_HANDLE_VALUE)
        {
            cout<<"打开文件失败"<<endl;
            return 0;
        }
        //创建文件映射对象
        HANDLE hFileMap=CreateFileMapping(hFile,NULL,PAGE_READONLY,0,0,NULL);
        if(hFileMap==NULL)
        {
            CloseHandle(hFile);
            cout<<"创建文件映射对象失败"<<endl;
            return 0;
        }
        //获取文件大小
        DWORD FileSizeHigh,FileSizeLow;
        FileSizeLow=GetFileSize(hFile,&FileSizeHigh);
        //在这里如果想要获取超过4GB文件的大小
        __int64 FileSize=FileSizeLow+(FileSizeHigh<<32);
        CloseHandle(hFile);
        __int64 FileOffSet=0,NumOf0s=0;
        DWORD dwBytesInBlock;
        while(FileSize>0)
        {
            dwBytesInBlock=si.dwAllocationGranularity;
            if(FileSize<si.dwAllocationGranularity)
            {
                dwBytesInBlock=(DWORD)FileSize;
            }
            PBYTE pbFile=(PBYTE)MapViewOfFile(hFileMap,FILE_MAP_READ,(DWORD)(FileOffSet>>32),(DWORD)(FileOffSet&0xFFFFFFFF),dwBytesInBlock);
            for(DWORD dwByte=0;dwByte<dwBytesInBlock;dwByte++)
            {
                if(pbFile[dwByte]==0)
                {
                    NumOf0s++;
                }
            }
            UnmapViewOfFile(pbFile);
            FileOffSet+=dwBytesInBlock;
            FileSize-=dwBytesInBlock;
        }
        CloseHandle(hFileMap);
        return NumOf0s;
    }

    这里需要注意的是文件的位移一定需要是分配粒度的倍数,所以,当所剩的大小大于分配粒度时 dwBytesInBlock等于分配粒度,否则等于文件剩下的大小

    测试结果:
    4796

    展开全文
  • 与虚拟内存一样,内存映射文件可以用来保留一个地址空间的区域,并将物理存储器提交给该区域。它们之间的差别是,物理存储器来自一个已经位于磁盘上的文件,而不是系统的页文件。一旦该文件被映射,就可以访问它,就...
  • 内存映射文件机制处理大文件 分类: 知识(Knowledge)2013-11-02 19:03 318人阅读 评论(0) 收藏 举报 先说结论:使用内存映射文件处理大文件可以提高效率。  为什么呢? 我们先来看看如果不使用...
  • 现在我有很多的图片,我想把图片文件映射到内存上面,然后在把内存映射的图片文件 读取出来,进行操作请问怎么操作
  • 使用内存映射文件处理大文件

    千次阅读 2014-05-21 11:50:26
    例如,在使用内存映射文件时,为了提高速度,系统将文件的数据页面进行高速缓存,而且在处理文件映射视图时不立即更新文件的磁盘映像。为解决这个问题可以考虑使用FlushViewOfFile()函数,该函数强制系统将修改过的...
  • VC++中使用内存映射编程方面的资料,希望对大家有用; 彻底共享,决不要分!
  • VC中用内存映射文件处理大文件

    千次阅读 2005-05-19 21:52:00
    VC中用内存映射文件处理大文件
  • 内存映射修改大文件

    千次阅读 2015-06-02 09:15:51
    本文介绍利用内存映射文件修改大文件:在大文件内存前加入一段数据,若要使用内存映射文件,必须执行下列操作步骤: 1.创建或打开一个文件内核对象,该对象用于标识磁盘上你想用作内存映射文件文件; 2.创建一个...
  • VC++中使用内存映射编程方面的资料,希望对大家有用; 彻底共享,决不要分!
  • vs2008 C++内存映射文件处理图像拼接源码内存映射文件处理图像拼接源码内存映射文件处理图像拼接源码内存映射文件处理图像拼接源码

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 310,411
精华内容 124,164
关键字:

内存映射处理大文件