日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

分块内存映射处理大文件-例子

發布時間:2023/12/15 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 分块内存映射处理大文件-例子 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

參考 :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 framesBOOL bLoop = TRUE;int i;int width = 1024;int height = 576;int bitcount = 8; //1, 4, 8, 24, 32////Build bitmap headerBITMAPFILEHEADER bitmapFileHeader; BITMAPINFOHEADER bitmapInfoHeader; BYTE rgbquad[4]; // RGBQUADint 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]; // 我的位圖pMyBmpBYTE *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; //rgbReservedfor(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; //rgbReservedfor(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 systemHANDLE 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 objectHANDLE 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 handleif (hFile != INVALID_HANDLE_VALUE){CloseHandle(hFile);hFile = INVALID_HANDLE_VALUE;}SetLastError(dwError);bLoop = FALSE;return FALSE;}// Retrieve allocation granularitySYSTEM_INFO sinf;GetSystemInfo(&sinf);DWORD dwAllocationGranularity = sinf.dwAllocationGranularity;// Retrieve file size// Retrieve file sizeDWORD 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 Handleif (hMapping != NULL){CloseHandle(hMapping);hMapping = NULL;}SetLastError(dwError);bLoop = FALSE;return FALSE;}BYTE *lpBits = (BYTE *)lpData;BYTE *curr1, *curr2, *lpEnd;curr1 = lpBits; // seek to startcurr2 = lpBits + 596; // seek to first framelpEnd = lpBits + dwBytesInBlock; // seek to end// Read video infomationKMemDataStream 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;}

總結

以上是生活随笔為你收集整理的分块内存映射处理大文件-例子的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。