国产精品1024永久观看,大尺度欧美暖暖视频在线观看,亚洲宅男精品一区在线观看,欧美日韩一区二区三区视频,2021中文字幕在线观看

  • <option id="fbvk0"></option>
    1. <rt id="fbvk0"><tr id="fbvk0"></tr></rt>
      <center id="fbvk0"><optgroup id="fbvk0"></optgroup></center>
      <center id="fbvk0"></center>

      <li id="fbvk0"><abbr id="fbvk0"><dl id="fbvk0"></dl></abbr></li>

      大批量文件數(shù)據(jù)存放和讀取方法

      文檔序號:6614991閱讀:323來源:國知局
      專利名稱:大批量文件數(shù)據(jù)存放和讀取方法
      技術(shù)領(lǐng)域
      本發(fā)明涉及軟件技術(shù)領(lǐng)域,尤指一種大批量文件數(shù)據(jù)存放和讀取方法。
      背景技術(shù)
      隨著計算才幾的"f及和應(yīng)用,需要存取的文件數(shù)據(jù)M來越多。所述文件凄t據(jù)泛
      指一切可以^f絲在計算才;u組上的數(shù)據(jù)文件。所述存取指^[絲計算機內(nèi)存中的數(shù)據(jù) 到文件上與讀取文件上的數(shù)據(jù)到計算機內(nèi)存中。少量的文件數(shù)據(jù)的存耳"十系統(tǒng)資源 影響不大,而大批量的數(shù)據(jù)文件的存取的方式直接影響到系統(tǒng)資源的利用。所述大 批量指數(shù)量超過io個以上。
      如圖l所示, 一絲講,對于大批量文件數(shù)據(jù)的存 常是把大批量的文件數(shù)據(jù) 分別保存在計算機硬盤上,然后再分別單獨對某個文件創(chuàng)建一個文件IO (InputOutput,輸入輸出)接口,從而實現(xiàn)對各個文件的操作。所逝04妄口,在這 里特指對文件數(shù)據(jù)的輸入輸出接口 。
      由上述可知,由于大批量的文件分別散落在硬盤上的各個地方,對整個應(yīng)用系 統(tǒng)會產(chǎn)生很多的問題。所述應(yīng)用系統(tǒng)在it^指一種計算才;i4欠件,它的正常運行, 需^l負(fù)于一些數(shù)據(jù)文件提供的數(shù)據(jù)。
      首先,應(yīng)用系統(tǒng)名^十某個文件進行存耳又,都需要針對該文件創(chuàng)建一個新的文件 10#口,這樣要浪費很多時間在IOt妄口的創(chuàng)建與銷tiJi,浪費很多系統(tǒng)資源;
      其次,樸文4憤落在石tiS:上還不利于應(yīng)用系統(tǒng)的安全,因為這些零散的文件 有可能被誤刪除或者誤》務(wù)改,從而導(dǎo)致應(yīng)用系統(tǒng)運行出錯;
      再者,M文fm落在石liLL還不利于應(yīng)用系統(tǒng)的可移植性,因為在移才lit匕系 統(tǒng)到其#^幾器上后,需要M相應(yīng)的M數(shù)據(jù)文件都移植過去,有可能出現(xiàn)漏拷, 從而導(dǎo)致應(yīng)用系統(tǒng)運行出錯。

      發(fā)明內(nèi)容
      本發(fā)明^^解決的問題是提供一種節(jié)約系統(tǒng)資源的大批量文件數(shù)據(jù)存放禾"賣取方法。為了解決上述問題,本發(fā)明大批量文件數(shù)據(jù)存放方法的技術(shù)方案包括
      將所有小文件的數(shù)據(jù)合并成一個大文件; 建立每個小文件的文件名及其文件編號的一一對應(yīng)關(guān)系; 建立每個所述丈件編號與小文件的文件信息的對應(yīng)關(guān)系,所述文件信息包括所 述小文件在所述大文件中的位置。
      其中,所述文件信息還包括所述小文件的文件大小。
      相應(yīng)地,本發(fā)明大批量文件數(shù)據(jù)讀取方法,用于讀取按照本發(fā)明大批量文件數(shù) 據(jù)存放方法的技術(shù)方案存放的文件數(shù)據(jù),包括步驟
      根據(jù)小文件的文件名來獲得所述小文件的文件編號;
      根據(jù)所述文件編號獲得所述小文件的文件信息;
      根據(jù)所述文件信息獲得所述小文件在大文件中的位置;
      根據(jù)所述小文件在大文件中的位置,通過所述大文件的10接口實S^t所述小 文件數(shù)據(jù)的讀取。
      與現(xiàn)有技^M目比,本發(fā)明大批量文件數(shù)據(jù)存放和讀耳又方法的有益效果為 由于是將大批量的小文件合成一個大文件,還建立了小文件的文件名和其文件 編號的一一對應(yīng)關(guān)系,又建立了小文件的文件編號與其文件信息的對應(yīng)關(guān)系。所述 文件信息包括小文件在大文件中的位置。這#^口道要存取的'J、文件的文件名就可獲 得其文件編號,獲得了文件編號就可知其文件信息,即其在大文件中的位置,因此, 通過大文件的IO接口就可讀出小文件的數(shù)據(jù),這樣大大節(jié)約了系統(tǒng)資源。


      圖l是現(xiàn)有技術(shù)對大批量文件數(shù)據(jù)存取的示意圖; 圖2是本發(fā)明大批量文件數(shù)據(jù)存放方法的流趕圖; 圖3是本發(fā)明大批量文件數(shù)據(jù)讀取方法的^^呈圖; 圖4是小文件的文件名與其文件編號的對應(yīng)示意圖; 圖5是小文件的文件編號與文件信息的對應(yīng)示意圖; 圖6是將大批量的小文件合并成一個大文件的示意圖; 圖7是對合并成的大文件的存取的示意具體實施例方式
      如圖l所示,本發(fā)明大批量文件數(shù)據(jù)存取方法包括
      步驟1)將所有小文件的數(shù)據(jù)合并成一個大文件;
      步驟2 )建立每個小文件的文件名及其文件編號的一一對應(yīng)關(guān)系;
      步驟3)建立每個所述文件編號與小文件的文件信息的對應(yīng)關(guān)系,所述文件信
      息包括所述'j 、文件在所述大文件中的位置。
      其中,所述文件信息還包括所述小文件的文件大小。
      由上述可知,本發(fā)明大批量文件數(shù)據(jù)存取方法是將所有小文件的數(shù)據(jù)合并成一
      個大文件,也;ttA合并成一個獨立的文件,這樣對該大文件進行存放和讀取的時候,
      只需要建立一個存》丈禾喊取該大文件的io接口就可以實m^于該大文件中的數(shù)據(jù)進
      行存放和讀取,如圖7所示。如圖6所示,該大文件的數(shù)據(jù)是由一個個小文件的數(shù) 據(jù)組成的。由于本發(fā)明大批量文件數(shù)據(jù)存取方法又建立了每個小文件的文件名及其 文件編號的——對應(yīng)關(guān)系,如圖4所示,也就是說,每一個小文件的文件名對應(yīng)唯 一一個文件編號。如圖5所示,本發(fā)明大批量文件數(shù)據(jù)存取方法還建立了小文件的 文件編號與該小文件在大文件中的文件信息的對應(yīng)關(guān)系,也就是說,知道了小文件 的文件編號就能夠知道該小文件的文件信息。
      相應(yīng)地,如圖2所示,本發(fā)明大批量文件數(shù)據(jù)讀取方法,用于讀耳又按照前述權(quán) 利要求所述的方法存放的文件數(shù)據(jù),包括
      步驟11)根據(jù)小文件的文件名來獲得所述小文件的文件編號;
      步驟12)根據(jù)所iiil件編號獲得所述小文件的文件信息;
      步驟13 )根據(jù)所述文件信息獲得所述小文件在大文件中的位置;
      步驟14)根據(jù)所述小文件在大文件中的位置,通過所述大文件的IO接口實現(xiàn) 對所述'J 、文件數(shù)據(jù)的讀取。
      由上述可知,按照本發(fā)明大批量文件數(shù)據(jù)存放方法存放大批量的小文件后,由 于已建立了小文件的文件名和其文件編號的一一對應(yīng)關(guān)系,因jtl^艮據(jù)要讀取的小文 件的文件名就可獲得其文件編號。另外也建立了小文件的文件編號和文件信息的對 應(yīng)關(guān)系,因此,得到了文件編號就可獲得小文件在大文件中的文件信息,如小文件 在大文件中的起始位置,文件的大小,這樣通過大文件的IO接口就可以實現(xiàn)對小 文件數(shù)據(jù)的讀取。
      下面采用本發(fā)明的方法對大批量的小文件進行存放和讀取。例如具有若干小文件,分別是"l.bmp", "2.bmp", "3.bmp",定義了5個全 局變量后,對每個函數(shù)調(diào)用"PutshFile("c:/l.bmp","l.bmp" , hOutPackage, filelndexList, fileldMapList, Itemld, Offset);"命令,就可以4巴這些文件合并到大文件"Data.dat"中。
      首先4組些小文件合并成一個大文件(將該大文件命名為"Data.dat"),然后建 立小文件的"文件名稱與文件ID (編號)對應(yīng)表"和"文件ID號與文件信息對應(yīng) 表"兩張表,這兩 錄分別^f呆存為"Data.map"文件和"Data.index',文件。
      下面是實現(xiàn)的偽代碼 a)定義數(shù)據(jù)結(jié)構(gòu)
      文件信息項的數(shù)據(jù)結(jié)構(gòu)如下 struct A3dFilelnfoItem
      DWORD m—id;〃文件ID號
      INT64 m—offset;〃文件在大文件中的起始位置
      int m—length;〃文件的長度
      };
      文件ID與文件名稱的映射項的lt據(jù)結(jié)構(gòu)如下 struct A3dFileldFileNameMapItem
      DWORD m一id; 〃文件E)號 char m—nameLen;〃文4牛名稱的長度 char* m—name;〃文4牛的名稱
      };
      b)定義5個重要的4^局變量
      std::list〈 A3dFilelnfoltem *〉 filelndexList;〃文件信息彬且 std::list〈 A3dFileldFileNameMapItem *> fileldMapList;〃文件DD與名稱凄tl且 DWORD 一ItemId,文件ID號 INT64 —OiTseMV/文付的起始位置 HANDLE hOutPackage;〃輸出大文件的句柄 hOutPackage=::CreateFile(DataFileName, GENERIC—READ1GENERIC一WRITE,FILESHARE—READ|FILE SHARE—WRITE, NULL,
      CREATE_ALWAYS, FILE ATTRIBUTE NORMAL/* | FILE—FLAG—OVERLAPPED | FILE—FLAG—NO—BUFFERING*/, NULL);〃 創(chuàng)建大文件的IO句柄
      c)寫一個函數(shù)PutshFile:這個函數(shù)實SW巴一個文件的數(shù)據(jù)合并到一個大文件中 去。用法如下
      輸入考4tfilenarne:要合并到大文件中的 '、文件的完整路徑名稱; 輸入^ltfileStrld:要合并到大文件中的小文件的唯一名稱標(biāo)識; l#7v#ltstd::list<A3dFileIndexItem*>& IndexList:文件信息數(shù)組 輸入^ltstd::list<A3dFileIdMapItem*>& IdMapList:文件ID與名稱凄U且 ^lTA##DWORD& Itemld:文件ID號 輸入^ltlNT64 &Offset:文件的起始位置
      該函凄史的用法示例PutshFile("c:/l.bmp", "l.bmp" , hOutPackage, fileIndexList, fileldMapList,Itemld,Offset);其中,"c:/l.bmp"指的是小文件的^4圣,"l.bmp"指的 是小文件的文件唯一名稱標(biāo)識,其它后面的5個參數(shù)為上面定義的5個全局變量。該 函數(shù)會把"c:/l.bmp"這個文件添加到大文件的末尾,并且為"l.bmp"生成一個唯一 的ID號,為filelndexListit個全局變量增加一條新的記錄,為IdMapList這個全局變量 增加一條新的記錄。
      該函數(shù)^t碼如下 Bool PutshFile(CString filename,CString fileStrld,
      HANDLE hPackage, std: :list<A3dFileIndexItem*>& IndexList, std: :list<A3dFileIdMapItem*>& IdMapList, DWORD& Itemld,INT64 &Offset)
      〃創(chuàng)建小文件的文件句柄,該句柄可用于讀取小文件的文件數(shù)據(jù) HANDLE hFile=::CreateFile(filename, GENERIC—READ|GENERIC—WRITE,FILE SHARE—READ|FILESHARE_WRnE, NULL,
      OPEN—EXISTING, FILE ATTRIBUTE NORMAL, NULL); 〃如果創(chuàng)建失敗,提示讀取文件失敗,并退出 if(hFile=INVALID—HANDLE VALUE)
      A&MessageBox(CString("Read File Fail :")+filename); return false;
      〃利用句柄,得到文件的長度信息 DWORD high32;
      DWORD low32=::GetFileSize(hFile,&high32); 〃如果得到長度為0,說明該小文件沒有數(shù)據(jù),提示沒有數(shù)據(jù)后退出 if(high32=0&&low32=0)
      AfidVIessageBox(CString("O File size :")+filename); return false;
      〃定義字符凄H且"static std::vector<char> buffer"用于i朱存小文件的數(shù)據(jù)
      DWORD numberO氾ytes;
      OVERLAPPED ol;
      static std::vector<char> buffer;
      buffer ,resize(low32); 〃讀取d 、文件的數(shù)據(jù)到字符數(shù)組"static std: :vectoKchar〉 buffer"中
      〃read file
      memset(&ol,0,sizeof(ol));
      if(FALSE = ::ReadFile(hFile, (LPVOID)&buffer
      , (DWORD)low32, &numberOffiytes, &ol》
      A&MessageBox("ReadFileEnror"); return false;
      8〃把小文件的數(shù)據(jù)添加到大文4牛的末尾
      〃write file
      memset(&ol,0,sizeof(ol)); ol.Offset=Offset&0xffiffffi; ol.OffsetHigh=Offset〉>32; if(FALSE
      =::WriteFne(hPackage,(LPVOID)&buffer
      ,low32,&numberOfBytes,&o1》
      AficMessageBox("WriteFileEnror"); return false;
      〃為filelndexList這個全局變量增加一條新的"文件ID號與文件信息"記錄 〃 filelndex
      A3dFilelndexItem承item=new A3dFilelndexItem(); 〃新建一知己錄
      item->m—id=ltemld; 〃該小文件ID號
      item->m—offsetK)ffset; 〃該d 、文件在大文件中的起始位置
      item-〉m—length=low3 2; 〃該'J 、文件的長度
      IndexList.push—back(item); 〃添加該信息到filelndexList凄tiBL中
      〃為IdMapList這個全局變量增加一條新的"文件名稱與文件ID號"記錄 〃 file畫ap
      CString —filename=fileStrId; 一filename.Replace('/VW);
      A3dFileIdMapItem* item = new A3dFileldMapItem(); 〃新建一^i己錄 item-〉m—icNItemld; 〃該小文件ID號
      item->m—nameLen=—filename.GetLength(); 〃i亥小文4牛的文4牛名長度 item->m_name=new char[item->m_nameLen+1 ]; 〃該小文4牛的文4牛名memset(item->m—name,0,item->m—nameLen+1); strcpy(item畫〉m—name,—filename);
      IdMapListpush—back(item);〃添力口該信息到IdMapList數(shù)組中
      Itemld++; 〃添加一個小文件后,文件ID號相應(yīng)加1 Offset+=low32; 〃添加一個小文件后,記錄文4快始位置的變量Offset也 要相應(yīng)增力口
      ::CloseHandle(hFile); 〃關(guān)閉小文件的句柄,返回添加成功信息 return true;
      d) 如c)步驟所述,重復(fù)調(diào)用PutshFile,把各個小文件合成到大文件中。
      e) 寫一個類,A3dFileldMap,它實現(xiàn)保存"文件名稱與文件ID對應(yīng)表"到文件 "Data.map"中,并實現(xiàn)讀取文件"Data.map"的凝:據(jù)到類中,并支持用戶4是供一個
      文件名就可以查詢到該文件的文件ID號。 class A3dFileldmap
      Public:
      〃保存"文件名稱與文件ID對應(yīng)表"的函數(shù) Bool saveFileldMap(CString filename,
      std: :list<A3dFileIdMapItem*>&固apList); 〃讀取數(shù)據(jù)文件,4al丈據(jù)加載到類的m一filenameldMap數(shù)據(jù)中 Bool Load(LPCSTR filename); 〃才艮據(jù)文件名稱,查詢文件ID號 Bool getFilelnfo(std::string name,DWORD& id); Private:
      Std::map〈std::string, A3dFileldFileNameMapItem *> m一filenameldMap;〃存 放文件名與文件名稱映射記錄的紅黑樹
      };
      〃文4牛頭IU居結(jié)構(gòu)
      struct A3dFileldMapHeader
      10char m一LenFileTag;〃文件標(biāo)識的長度 char* m一filetag;〃文件標(biāo)識 int m一version;〃文件版本
      int 111一1^1111;//文件名稱與文件10號的記錄的條數(shù)
      };
      〃保存"文件名稱與文件ID對應(yīng)表,,的函數(shù) Bool A3dFileldmap::saveFileldMap(CString filename, std: :list<A3dFileIdMapItem*>& IdMapList)
      A3dFileldMapHeaderfileldMapHeader;
      fileldMapHeader,m—LenFileTag=l 6; 〃文4牛才示i口、的長度 fileldMapHeader.m—filetag=new char[fileIdMapHeader.m—LenFileTag+1 ];
      memset(fileldMapHeader.m一filetag,0,fileldMapHeader.m—LenFileTag+l); strcpy(fileldMapHeader.m—filetag,"IdMapTableHeader");〃文件標(biāo)識 fileldMapHeader,m—version=1001; 〃文件版本 fileldMapHeader.m—iNuiTp4dMapList.size();〃^i己錄臺々^"凄t
      〃把文件頭寫上到文件中,
      〃把IdMapList數(shù)組中的^i己錄寫到文件中
      FILE* fy = fopen(filename,"wb");〃打開文件,進行只寫操作
      fWrite(&header->m—LenFileTag,sizeof(header->m—LenFileTag), 1 ,粉;〃寫入
      文件標(biāo)識的長度
      fWrite(header->m—filetag,sizeof(char),header畫〉m一LenFileTag,脈 〃 寫入文件 標(biāo)識
      fWrite(&header->m—version,sizeo《header->m—version), 1 ,制; 〃寫AJ/反本號 fWrite(&header->m—iNum,sizeof(header-〉m一iNum), 1 ,粉; 〃 寫入映射條數(shù)〃逐條寫入文件ID號與文件名稱的映射
      for(int i=0;i<m_pHeader->m—iNum;i++)
      A3dFileIdMapItem* item = IdMapList [i]; 涵te(&item-〉mjd,sizeof(DWORD),l辦);〃寫入文件ID號 fWrite(&item-〉m—nameLen,sizeof(char), 1 ,粉; 〃寫入文件名稱長度 f\vrite(item->m—name,sizeof(char),item->m—nameLen,脈 〃寫入文件名

      Fclose(^));〃關(guān)閉文件 return true;
      〃讀取數(shù)據(jù)文件,把數(shù)據(jù)加載到類的m—filenameldMap數(shù)據(jù)中 Bool A3dFileldmap::Load(LPCSTR filename)
      FILE* * = fopen(filename,"rb");〃打開文件,進行只讀操作 〃讀取文件頭
      A3dFileIdMapHeader* pHeadei^new A3dFileldMapHeader(); if(fread(&pHeader-〉m—LenFileTag,sizeof(pHeader->m_LenFileTag),l,f^)= NULL) //讀取文件標(biāo)識的長度
      goto fail; 〃失敗處理 pHeader-〉m—filetag^new char[pHeader->m—LenFileTag+1 ]; memset(pHeader-〉m—filetag,0,pHeader->m—LenFileTag+1); if(fread(pHeader->m—filetag,sizeof(char),pHeader->m—LenFileTag,i|))=NUL L)〃讀取文件標(biāo)識
      goto fail; 〃失M理 〃讀取文件版本號
      if(fread(&pHeader-〉m—version,sizeof(pHeader->m—version), 1 ,^))=NULL)
      goto fail; 〃失敗處理 〃讀取記錄條數(shù)if(fread(&pHeader->m—iNum,sizeof(pHeader-〉mjNum), 1,1^))=NULL)
      goto fail; 〃失艦理 〃讀f^^i己錄,并加入到紅黑樹中 for(inti=0;i<m_pHeader->m—iNum;i++)
      A3dFileIdMapItem* item = new A3dFileldMapItem(); 〃讀取文件ID號
      if(fread(&item->m—id,sizeof(DWORD), 1 ,Qd)^NULL)
      goto fail; 〃失敗處理 〃讀取文件名的長度
      if(fread(&item->m—nameLen,sizeof(char), 1 ,i^)=NULL)
      goto fail; 〃失敗處理 item->m—name=new char[item->m—nameLen+1 ]; memset(item->m—name,0,item->m—nameLen十1);
      〃讀取文件名稱
      if(fread(item->m_name,sizeof(char),item-〉m_nameLen,f^)=NULL) goto fail; 〃失敗處理 〃添加記錄到紅黑樹中
      m—filenameldMap.insert(std: :pair<std:: string, A3 dFileIdMapItem*>(std ::string(item->m—name), item));
      Fclose(fy);〃關(guān)閉文件 return true; fail:return false;
      〃才艮據(jù)文件名稱,查詢文件ID號
      Bool A3dFileldmap::getFilelnfo(std::string name,DWORD& id)
      std: :map<std: :string,A3dFileIdMapItem*〉: :iterator it; it^m一filenameldMap.find(name);〃紅黑樹快速查詢if(it=m— filenameldMap.endOy/查詢失ii!^t理
      return false; A3dFileIdMapItem* item=it->second; id=item->m—id;Z/返回查詢到的ID號 return true;
      f)寫一個類,A3dFilelndex,它實現(xiàn)/f絲"文件ID與文件信息對應(yīng)表"到文件 "Data.index"中,并實現(xiàn)讀取文件"Data.index"的數(shù)據(jù)到類中,并支持用戶提供一 個文件ID號就可以查詢到該文件的文件信息。 class A3dFilelndex
      Public:
      〃保存"文件ID與文件信息對應(yīng)表"的函數(shù) Bool saveFilelndex(CString filename,
      std: :list<A3dFileIndexItem*>& IndexList); 〃讀取數(shù)據(jù)文件,4alt據(jù)加載到類的m—filenamelndexMap數(shù)據(jù)中 Bool Load(LPCSTR filename); 〃根據(jù)文件ID號,查詢文件信息 Bool getFilelnfo(DWORD id,INT64& offset,int& length); Private:
      Std::map〈DWORD, A3dFilelndexItem *> m—filenamelndexMap;〃存放文件 ID號與文件信息映射記錄的紅黑樹
      〃文件頭數(shù)據(jù)結(jié)構(gòu)
      struct A3dFilelndexHeader
      char m—LenFileTag; 〃文件標(biāo)識的長度
      char* m—filetag; 〃文件標(biāo)識
      int m—version; 〃文件版本
      int mJNum; 〃對應(yīng)的記錄的^l丈};
      〃保存"文件ro號與文件信息對應(yīng)表"的函數(shù)
      Bool A3dFilelndex ::saveFilelndex(CString filename,std: :list<A3dFileIndexItem*>& IndexList)
      A3dFilelndexHeader filelndexHeader;
      filelndexHeader,m—LenFileTag=l 6; 〃文件標(biāo)識的長度 filelndexHeader.m—filetag^ew char [filelndexHeader.m—LenFileTag+1 ]; memset(filelndexHeader.m—filetag,0,filelndexHeader.m—LenFileTag+1); strcpy(filelndexHeader.m—filetag,"IndexTableHeader");〃文件標(biāo)識 filelndexHeader.m—version: 1001; 〃文件版本
      filelndexHeader.m—iNum:IndexListsize();〃文件ID號與文件信息對應(yīng) 的記錄的條數(shù)
      甜巴文件頭寫上到文件中 〃把IndexList數(shù)組寫到文件中
      〃方法與A3dFileldmap::saveFileldMap的相關(guān)方法完t樣,iiLS不再贅述 return true;
      }
      〃讀^Jt據(jù)文件,把Jt據(jù)加載到類的m—filenameldMap數(shù)據(jù)中 Bool A3dFileldmap::Load(LPCSTR filename)
      FILE*= fopen(filename,"rb");〃打開文件,進行只讀操作 〃讀取文件頭
      A3dFileIndexHeader* pHeader=new A3dFilelndexHeader(); if(fread(&pHeader->m—LenFileTag,sizeof(pHeader->m—LenFileTag),l,fy)= NULL) //讀取文件標(biāo)識的長度
      goto fail; 〃失敗處理 pHeader->m—filetag=new char [pHeader-〉m—LenFileTag十1 ];memset(pHeader匪〉m—filetag,0,pHeader->m—LenFileTag十1); if(fread(pHeader->m—filetag,sizeof(char),pHeader畫〉m—LenFileTag,粉-NUL L)〃讀取文件標(biāo)識
      goto fail; 〃失敗處理 〃讀取文件版本號
      if(fread(&pHeader畫〉m—version,sizeof(pHeader->m—version),l,l^))=NULL)
      goto fail; //失敗處理 〃讀取記錄條數(shù)
      if(fread(&pHeader->m—iNum,sizeof(pHeader-〉m—iNum), 1 ,粉-NULL) goto fail; 〃失敗處理
      〃讀:^^i己錄,并加入到紅黑樹中
      for(int i=0;i<m_pHeader->m_iNum;i++)
      A3dFileIndexItem* item = new A3dFilelndexItem0; 〃讀取文件ID號
      if(fread(&item->m—id,sizeof(DWORD), 1 ,$)=NULL)
      goto fail; 〃失敗處理 〃讀取文件ID號
      〃讀取文件偏移位置,即在大文件中的起始位置信息
      〃讀取文件的大小信息
      〃添加記錄到紅黑樹中 m—
      filenameIndexMap.insert(std::pair<DWORDA3dFileIndexMapItem*>
      (文件ID號,item));
      Fclose(粉;〃關(guān)閉文件 return true; fail:return false;
      〃根據(jù)文件ID號,查詢文件信息
      Bool A3dFilelndexmap::getFilelnfo(DWORD id,INT64& offset,int& length)
      16std::map〈 DWORDA3dFileIndexMapItem*>::iterator it; it^m-filenamelndexMap.find(id);〃紅黑沖對快速查詢 if(it==m— filenamelndexMap.end()y/查詢失敗處理
      return false; A3dFileIndexMapItem* item=it->second; offset=item->m—offset;Z/返回查詢到的偏移位置 length=item->m—length; return true;
      對大文件的存取訪問,本例采用完成端口機制。所述完成端口機制指一種IO模 型,在這種模型中,能實現(xiàn)異步方式的調(diào)用。所述異步指在工作者A與工作者B協(xié)同 工作的情形下,工作者A向工作者B提交了工作請求后,工作者A不等待工作者B作 出反應(yīng)就立即離開,并且工作者B在^Vf亍完工作者A提交的一項工作請求后,有辦法 通知工作者A該項工作請求已經(jīng)完成。
      在本例中建立一個完成端口隊列,實現(xiàn)對大文件的異步存取操作。采用一個類 A3dSingleThreadlocpQueuelmplement來實現(xiàn)完成端口的創(chuàng)建,并實現(xiàn)利用完成端口 , 對大文件異步的進行存耳又訪問。
      該類暴露給用戶的接口主要是WriteFile函數(shù)和ReadFile函數(shù),這兩個函數(shù)可以實 現(xiàn)異步存取大文件的數(shù)據(jù)。
      類A3dSingleThreadlocpQueuelmplement的主^R/5馬3口下 class A3dSingleThreadlocpQueuelmplement
      private:
      HANDLE m—Wocp; 〃完成端口的句柄 HANDLE m—hWaitEvent; 〃事件 enum IocpOperation{DestroyIocp}; 〃完成端口 4喿作類型 protected:
      static DWORD WINAPI —WorkerThreadProc(LPVOID lpParam);〃
      工作者線程處理邏輯 A3dSingleThreadlocpQueuelmplement() {}
      〃向完成端口提交事件 virtual void Post(unsigned long numberO氾ytes, OVERLAPPED* overlapped);
      〃完成端口事件處理 virtual void QueuedEvent(DWORD numberO氾ytes, LPOVERLAPPED overlapped, BOOL success);
      〃負(fù)責(zé)具體實施讀出文件中的數(shù)據(jù)到內(nèi)存中 void Read(ReadWriteContext* context);
      〃負(fù)責(zé)具體實施寫入文件數(shù)據(jù)到大文件中 void Write(ReadWriteContext* context);
      struct ReadWriteContextZ/定義教:才居結(jié)構(gòu)ReadWriteContext
      OVERLAPPED ol; 〃完成端口重疊IO
      bool bRead; //是否是讀取操作的標(biāo)識
      std: :vector<char>* buffer; 〃字符數(shù)組,用于存放文件數(shù)據(jù)
      DWORD fileld; 〃文件ID號
      int length; 〃文件大小
      int icurLength; 〃已完成的文4牛大小
      INT64 offset; //偏移位置
      A3dlreceiver* receiver; 〃用于回調(diào)的通知對象
      CRITICAL—SECTION contextLock;
      };
      public:
      A3dSingleThreadlocpQueuelmplement();
      〃4巴^lt輸入的內(nèi)存寫入到大文件中 virtual bool WriteFile(DWORD fileld, std::vector<char〉* buffer); 〃從大文件中讀取某個文件的數(shù)據(jù)到內(nèi)存中 virtual void ReadFile(DWORD fileld, int fileLength,A3孤eceiver: receiver);
      18};
      類的關(guān)鍵實現(xiàn)函數(shù)代碼如下
      才&iL件數(shù)據(jù)寫入到大文件中的函數(shù)"WriteFile" ,^#t "fileld"為文件ID號, #|丈"std::vectoKchar>* buffer"為文件數(shù)據(jù)內(nèi)存 bool A3dSingleThreadlocpQueuelmplement::WriteFile(DWORD fileld, std::vector<char>* buffer)
      ReacTWriteContext* context=new ReadWriteContextO;〃奮r建一-欠i賣 寫操作的記錄
      ::EnterCriticalSection(&context隱〉contextLock); context-〉bRead二false;〃才示i口、為寫入^)犬態(tài) context->buffer=new std: :vector<char>(buffer->size()); tontext-〉buffeF傘buffer;〃復(fù)制文件數(shù)據(jù)到結(jié)構(gòu)體中 context-〉fileld-fileld;〃復(fù)制文件ID號到結(jié)構(gòu)體中
      context->length=context-〉buffer-〉size。;〃復(fù)制文件大d 、到結(jié)構(gòu)體中 context->icurLength=0; 〃當(dāng)前已完成的大小為0 context-〉offselK); //偏移位置暫時未知,設(shè)為0 ::LeaveCriticalSection(&context-〉contextLock);
      \\^6^01^乂化//這個函數(shù)具體實現(xiàn)了向大文件進行寫入功能
      return true;
      從大文件中讀取某個文件的數(shù)據(jù)到內(nèi)存中的函數(shù)"ReadFile",參數(shù)"fileld"為 文件ID號,"fileLength"為文件長>1信息,^!t "receiver"是用于回調(diào)的通 知對象,完成端口一旦完成讀取操作,就會通知"receiver"讀取完成。
      void A3dSingleThreadlocpQueuelmplement::ReadFile(DWORD fileld, int fileLengih.,A3dIReceiver* receiver)
      INT64 offset;
      〃查找"文件ID與文件信息對應(yīng)表,,,根據(jù)文件的ID得到文件的大 小與起始位置if(m_pFileIndex->getFileInfo(fileId,offset,fileLength))
      ReadWriteContext* context=new ReadWriteContext();〃新建一次 讀寫操作的記錄
      ::EnterCriticalSection(&context-〉contextLock); context->bRead=true; 〃才示識為讀耳又^l犬態(tài) context->buffer=new
      std:: vector<char>((fileLength+m—dwBlockSize-1 )&~(m—dwBlockSize
      隱l)); 〃開辟一段用于^f絲文件數(shù)據(jù)的內(nèi)存
      context->fileId=fileId; 〃復(fù)制文件ID號到結(jié)構(gòu)體中 context->length=fileLength; 〃復(fù)制文件大小到結(jié)構(gòu)體中 context->icurLength=0; 〃當(dāng)前已完成的大小為0 context-〉offset=offset; 〃復(fù)制偏移位置到結(jié)構(gòu)體中 contex-〉receivei^receiver;〃復(fù)制回調(diào)通知對象到結(jié)構(gòu)體中 ::LeaveCriticalSection(&context—〉contextLock);
      詳見Read函數(shù)的說明
      〃負(fù)責(zé)具體實施寫入文件數(shù)據(jù)到大文件中,應(yīng)該注意的是,該函數(shù)是私有函數(shù), 只能由WriteFile函數(shù)調(diào)用,由于是重疊端口,該函數(shù)每次被調(diào)用,都向大文件寫入小 文件的數(shù)提中的一段數(shù)據(jù)(通常為一個系統(tǒng)分頁大小)。用戶調(diào)用WriteFile函數(shù)后就 離開了,完成端口調(diào)用了該函數(shù),實現(xiàn)了向大文件寫入一段數(shù)據(jù)后,會判斷小文件 是否^卩被寫入完成了,如果未完成,完成端口會再次調(diào)用該函數(shù),直到小文件已 經(jīng)寫入完成了,這時,通知用戶文件寫入已經(jīng)完成。
      void A3dSingleThreadlocpQueuelmplement:: Write(ReadWriteContext* context)
      ::EnterCriticalSection(&context->contextLock);
      DWORD highSize;
      20DWORD lowSize;
      lowSize=GetFileSize(m—hCacheFile,&highSize);〃i^得大文件當(dāng)前 的長度,高32位長度和#32位長度 memset(&context-〉ol,0,sizeof(context->ol));
      (:01^乂1->01.€^561=10\¥8126;//更新結(jié)構(gòu)體的重疊端口的jl^32位偏移 信息
      context->ol.OffsetHigh=highSize; 〃更新結(jié)構(gòu)體的重疊端口的高32 位偏移^f言息
      if(context)icurLength^Oy/更新結(jié)構(gòu)體的偏移位置信息
      context-〉offset=((INT64)highSize) 32 | (INT64)lowSize; DWORD numberO氾ytes;
      int nLefl=context-〉length-context->icurLength;〃未冗成的大小等于
      文件大小再減去已完成的大小
      DWORD
      nToWrite=nLefi>m—dwBlockSize m—dwBlockSize:nLeft;〃決定本次
      寫^a喿作的大小,它為"未完成的大小"與"一個系統(tǒng)分頁的大 小"兩者之間的小者
      if(FALSE
      =::WriteFile(m—hCacheFile,(LPVOID)&(* context-〉buffer)[context畫 〉icurLength],nToWrite,&numberO氾ytes,(LPOVERLAPPED)contex
      t)y/進行寫入操作,并進行出錯處理
      switch(DWORD d = ::GetLastE畫(》
      case ERROR—HANDLE—EOF: break;
      case ERROR—IO一PENDING:
      break; default:
      throw d;::LeaveCriticalSection(&context->contextLock);
      〃負(fù)責(zé)M實施讀取大文件中數(shù)據(jù)到內(nèi)存中,應(yīng)該注意的是,該函凄t^私有函數(shù), 只能由ReadFile函數(shù)調(diào)用,由于是重疊端口,該函數(shù)每次被調(diào)用,都從大文件讀取一 段數(shù)據(jù)(通常為一個系統(tǒng)分頁大小),并^il段數(shù)據(jù)存放在內(nèi)存中。用戶調(diào)用ReadFile 函凄仏就離開了,完成端口調(diào)用了該函數(shù),實現(xiàn)了從大文件讀取一段數(shù)據(jù)存放在內(nèi) 存后,會判斷小文件是否4^卩被讀取完成了,如果未完成,完成端口會再次調(diào)用該 函數(shù),直到小文件數(shù)據(jù)已經(jīng)被全部讀取完成了,這時,通知用戶文件讀取已經(jīng)完成。 void A3dSingleThreadlocpQueuelmplement: :Read(ReadWriteContext* context)
      ::EnterCriticalSection(&context-〉contextLock);
      memset(&context->ol,0,sizeof(context-〉ol));
      context-〉ol.Offse1 ^ontext-〉offset&0xffffffff;〃更新重疊端口的 讀取位置信息,#32位
      context-〉ol.OffsetHigh=context->offset>〉32; 〃更新重疊端口的 讀取^位置信息,高32位
      DWORD numberOfBytes;
      DWORD nToRead;
      int nLeft=context-〉length-context->icurLength; 〃未冗成的大小 等于文件大小再減去已完成的大小
      if(context-〉icurLength%m—dwBlockSize=0)/A'j斷未完成的大 小是不是已經(jīng)小于一個系統(tǒng)分頁的大小了
      nToRead=nLeft>m—dwBlockSize m—dwBlockSize:nLeft;〃決定本次讀取操 作的大小,它為"未完成的大小"與"一個系統(tǒng)分頁的大小"兩者之間的小者
      else
      22DWORD
      nLastReadLeft=(context->icurLength+m—dwBlockSize-1 )&《m一dwB lockSize-1 )-context->icurLength; nToReacKefl^nLastReadLeft nLastReadLeft:nLeft;〃決定本次讀取4喿作 的大小,它為"未完成的大小"與"上次讀取4喿作未完成的大小"兩者之間的小者
      if(FALSE = ::ReadFile(m—hCacheFile, (LPVOID)&(*context->buffer)[context->icurLength], (DWORD)nToRead, &numberOffiytes, (LPOVERLAPPED)context))
      (y/進^s賣i^才喿作,并進行出錯處理
      switch(DWORD d = ::GetLastError(》
      case ERROR—HANDLE—EOF: break;
      case ER ROR—IO PENDING:
      break; default:
      throw d;
      ::LeaveCriticalSection(&context->contextLock);
      例如要讀取小文件,首先要讀取"文件名稱與文件ID映射表"文件與"文件 ID與文件信息映射表"文件。全局變量"A3dFileldmap * g_pFileIDmap"用于<絲 "文件名稱與文件id映射表"類的指針,全局變量"A3dFileIndexmap* g_pFileIndexmap,,用于保存"文件ID號與文件信息表"類的指針。分別調(diào)用這兩 個類的Load函數(shù),就可以,"件中,"tei^兩個信息M載到內(nèi)存中。
      例如,需要讀取文件"l.bmp ",則可以先調(diào)用 "DWORDid;g_pFileIDmap->getFileInfo(std::string("l.bmp",id)"得到"l.bmp"的文件K)號;然 后再調(diào)用"INT64 offset;intlength;g_pFileIndexmap->getFileInfo(id,offset,length)"得到 該文件的長度length;接著,設(shè)定一個"用于接收完成通知的回調(diào)通知者,,對象 "receiver " ; 最后調(diào)用 完成端 口 的 函數(shù) A3dSingleThreadlocpQueuelmplement::ReadFile(id,length,receiver)。這樣,應(yīng)用程序就 可以立即離開,等完成端口把文件讀取完成,它會把通知給receiver對象,并把文 件的內(nèi)容發(fā)給receiver對象。
      如果要保存文件 "l.bmp ", 則可以先調(diào)用 "DWORD id;g_pFileIDmap->getFileInfo(std::string("l.bmp",id)"得到"l.bmp"的文件ID號;然 后再把文件的內(nèi)^f果存到變量"std::vector<char>* buffer"中,調(diào)用完成端口的函凄t A3dSingleThreadlocpQueuelmplement::WriteFile(id,buffer)。 il才羊,應(yīng)用禾呈序t尤可以立 即離開,完成端口會完成寫入操作。
      綜上所述,由于是將大批量的小文件合成一個大文件,還建立了小文件的文件 名和其文件編號的一一對應(yīng)關(guān)系,又建立了小文件的文件編號與其文件信息的對應(yīng)
      關(guān)系。所iii:件信息包括小文件在大文件中的位置。這才抖口道要存取的小文件的文 件名就可獲得其文件編號,獲得了文件編號就可知其文件信息,即其在大文件中的 位置,因此,通過大文件的io接口就可讀出小文件的數(shù)據(jù),這樣大大節(jié)約了系統(tǒng) 資源。
      權(quán)利要求
      1、一種大批量文件數(shù)據(jù)存放方法,其特征在于,包括步驟將所有小文件的數(shù)據(jù)合并成一個大文件;建立每個小文件的文件名及其文件編號的一一對應(yīng)關(guān)系;建立每個所述文件編號與小文件的文件信息的對應(yīng)關(guān)系,所述文件信息包括所述小文件在所述大文件中的位置。
      2、 如權(quán)利要求l所述的大批量文件數(shù)據(jù)存放方法,其特征在于,所述文件信 息還包括所述小文件的文件大小。
      3、 一種大批量文件數(shù)據(jù)讀取方法,用于讀取按照前述權(quán)利要求所述的方法存 放的文件數(shù)據(jù),其特征在于,包括步驟沖艮據(jù)小文件的文件名來獲得所述小文件的文件編號; 根據(jù)所述文件編號獲得所述小文件的文件信息; 根據(jù)所述文件信息荻得所述小文件在大文件中的位置; 根據(jù)所述小文件在大文件中的位置,通過所述大文件的10接口實m^f所述小 文件l封居的讀取。
      全文摘要
      本發(fā)明公開一種大批量文件數(shù)據(jù)存取方法,包括將所有小文件的數(shù)據(jù)合并成一個大文件;建立每個小文件的文件名及其文件編號的一一對應(yīng)關(guān)系;建立每個所述文件編號與小文件的文件信息的對應(yīng)關(guān)系,所述文件信息包括所述小文件在所述大文件中的位置。相應(yīng)地,本發(fā)明還公開一種大批量文件數(shù)據(jù)讀取方法,用于讀取按照本發(fā)明的存放方法存放的文件數(shù)據(jù),包括步驟根據(jù)小文件的文件名來獲得所述小文件的文件編號;根據(jù)所述文件編號獲得所述小文件的文件信息;根據(jù)所述文件信息獲得所述小文件在大文件中的位置;根據(jù)所述小文件在大文件中的位置,通過所述大文件的IO接口實現(xiàn)對所述小文件數(shù)據(jù)的讀取。采用本發(fā)明的技術(shù)方案能夠節(jié)約系統(tǒng)資源。
      文檔編號G06F17/30GK101452465SQ20071019900
      公開日2009年6月10日 申請日期2007年12月5日 優(yōu)先權(quán)日2007年12月5日
      發(fā)明者易國真 申請人:高德軟件有限公司
      網(wǎng)友詢問留言 已有0條留言
      • 還沒有人留言評論。精彩留言會獲得點贊!
      1