大批量文件数据存放和读取方法

文档序号:6614991阅读:295来源:国知局
专利名称:大批量文件数据存放和读取方法
技术领域
本发明涉及软件技术领域,尤指一种大批量文件数据存放和读取方法。
背景技术
随着计算才几的"f及和应用,需要存取的文件数据M来越多。所述文件凄t据泛
指一切可以^f絲在计算才;u組上的数据文件。所述存取指^[絲计算机内存中的数据 到文件上与读取文件上的数据到计算机内存中。少量的文件数据的存耳"十系统资源 影响不大,而大批量的数据文件的存取的方式直接影响到系统资源的利用。所述大 批量指数量超过io个以上。
如图l所示, 一絲讲,对于大批量文件数据的存 常是把大批量的文件数据 分别保存在计算机硬盘上,然后再分别单独对某个文件创建一个文件IO (InputOutput,输入输出)接口,从而实现对各个文件的操作。所逝04妄口,在这 里特指对文件数据的输入输出接口 。
由上述可知,由于大批量的文件分别散落在硬盘上的各个地方,对整个应用系 统会产生很多的问题。所述应用系统在it^指一种计算才;i4欠件,它的正常运行, 需^l负于一些数据文件提供的数据。
首先,应用系统名^十某个文件进行存耳又,都需要针对该文件创建一个新的文件 10#口,这样要浪费很多时间在IOt妄口的创建与销tiJi,浪费很多系统资源;
其次,朴文4愤落在石tiS:上还不利于应用系统的安全,因为这些零散的文件 有可能被误删除或者误》务改,从而导致应用系统运行出错;
再者,M文fm落在石liLL还不利于应用系统的可移植性,因为在移才lit匕系 统到其#^几器上后,需要M相应的M数据文件都移植过去,有可能出现漏拷, 从而导致应用系统运行出错。

发明内容
本发明^^解决的问题是提供一种节约系统资源的大批量文件数据存放禾"卖取方法。为了解决上述问题,本发明大批量文件数据存放方法的技术方案包括
将所有小文件的数据合并成一个大文件; 建立每个小文件的文件名及其文件编号的一一对应关系; 建立每个所述丈件编号与小文件的文件信息的对应关系,所述文件信息包括所 述小文件在所述大文件中的位置。
其中,所述文件信息还包括所述小文件的文件大小。
相应地,本发明大批量文件数据读取方法,用于读取按照本发明大批量文件数 据存放方法的技术方案存放的文件数据,包括步骤
根据小文件的文件名来获得所述小文件的文件编号;
根据所述文件编号获得所述小文件的文件信息;
根据所述文件信息获得所述小文件在大文件中的位置;
根据所述小文件在大文件中的位置,通过所述大文件的10接口实S^t所述小 文件数据的读取。
与现有技^M目比,本发明大批量文件数据存放和读耳又方法的有益效果为 由于是将大批量的小文件合成一个大文件,还建立了小文件的文件名和其文件 编号的一一对应关系,又建立了小文件的文件编号与其文件信息的对应关系。所述 文件信息包括小文件在大文件中的位置。这#^口道要存取的'J、文件的文件名就可获 得其文件编号,获得了文件编号就可知其文件信息,即其在大文件中的位置,因此, 通过大文件的IO接口就可读出小文件的数据,这样大大节约了系统资源。


图l是现有技术对大批量文件数据存取的示意图; 图2是本发明大批量文件数据存放方法的流趕图; 图3是本发明大批量文件数据读取方法的^^呈图; 图4是小文件的文件名与其文件编号的对应示意图; 图5是小文件的文件编号与文件信息的对应示意图; 图6是将大批量的小文件合并成一个大文件的示意图; 图7是对合并成的大文件的存取的示意具体实施例方式
如图l所示,本发明大批量文件数据存取方法包括
步骤1)将所有小文件的数据合并成一个大文件;
步骤2 )建立每个小文件的文件名及其文件编号的一一对应关系;
步骤3)建立每个所述文件编号与小文件的文件信息的对应关系,所述文件信
息包括所述'j 、文件在所述大文件中的位置。
其中,所述文件信息还包括所述小文件的文件大小。
由上述可知,本发明大批量文件数据存取方法是将所有小文件的数据合并成一
个大文件,也;ttA合并成一个独立的文件,这样对该大文件进行存放和读取的时候,
只需要建立一个存》丈禾喊取该大文件的io接口就可以实m^于该大文件中的数据进
行存放和读取,如图7所示。如图6所示,该大文件的数据是由一个个小文件的数 据组成的。由于本发明大批量文件数据存取方法又建立了每个小文件的文件名及其 文件编号的——对应关系,如图4所示,也就是说,每一个小文件的文件名对应唯 一一个文件编号。如图5所示,本发明大批量文件数据存取方法还建立了小文件的 文件编号与该小文件在大文件中的文件信息的对应关系,也就是说,知道了小文件 的文件编号就能够知道该小文件的文件信息。
相应地,如图2所示,本发明大批量文件数据读取方法,用于读耳又按照前述权 利要求所述的方法存放的文件数据,包括
步骤11)根据小文件的文件名来获得所述小文件的文件编号;
步骤12)根据所iiil件编号获得所述小文件的文件信息;
步骤13 )根据所述文件信息获得所述小文件在大文件中的位置;
步骤14)根据所述小文件在大文件中的位置,通过所述大文件的IO接口实现 对所述'J 、文件数据的读取。
由上述可知,按照本发明大批量文件数据存放方法存放大批量的小文件后,由 于已建立了小文件的文件名和其文件编号的一一对应关系,因jtl^艮据要读取的小文 件的文件名就可获得其文件编号。另外也建立了小文件的文件编号和文件信息的对 应关系,因此,得到了文件编号就可获得小文件在大文件中的文件信息,如小文件 在大文件中的起始位置,文件的大小,这样通过大文件的IO接口就可以实现对小 文件数据的读取。
下面采用本发明的方法对大批量的小文件进行存放和读取。例如具有若干小文件,分别是"l.bmp", "2.bmp", "3.bmp",定义了5个全 局变量后,对每个函数调用"PutshFile("c:/l.bmp","l.bmp" , hOutPackage, filelndexList, fileldMapList, Itemld, Offset);"命令,就可以4巴这些文件合并到大文件"Data.dat"中。
首先4組些小文件合并成一个大文件(将该大文件命名为"Data.dat"),然后建 立小文件的"文件名称与文件ID (编号)对应表"和"文件ID号与文件信息对应 表"两张表,这两 錄分别^f呆存为"Data.map"文件和"Data.index',文件。
下面是实现的伪代码 a)定义数据结构
文件信息项的数据结构如下 struct A3dFilelnfoItem
DWORD m—id;〃文件ID号
INT64 m—offset;〃文件在大文件中的起始位置
int m—length;〃文件的长度
};
文件ID与文件名称的映射项的lt据结构如下 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);〃 创建大文件的IO句柄
c)写一个函数PutshFile:这个函数实SW巴一个文件的数据合并到一个大文件中 去。用法如下
输入考4tfilenarne:要合并到大文件中的 '、文件的完整路径名称; 输入^ltfileStrld:要合并到大文件中的小文件的唯一名称标识; l#7v#ltstd::list<A3dFileIndexItem*>& IndexList:文件信息数组 输入^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"指的 是小文件的文件唯一名称标识,其它后面的5个参数为上面定义的5个全局变量。该 函数会把"c:/l.bmp"这个文件添加到大文件的末尾,并且为"l.bmp"生成一个唯一 的ID号,为filelndexListit个全局变量增加一条新的记录,为IdMapList这个全局变量 增加一条新的记录。
该函数^t码如下 Bool PutshFile(CString filename,CString fileStrld,
HANDLE hPackage, std: :list<A3dFileIndexItem*>& IndexList, std: :list<A3dFileIdMapItem*>& IdMapList, DWORD& Itemld,INT64 &Offset)
〃创建小文件的文件句柄,该句柄可用于读取小文件的文件数据 HANDLE hFile=::CreateFile(filename, GENERIC—READ|GENERIC—WRITE,FILE SHARE—READ|FILESHARE_WRnE, NULL,
OPEN—EXISTING, FILE ATTRIBUTE NORMAL, NULL); 〃如果创建失败,提示读取文件失败,并退出 if(hFile=INVALID—HANDLE VALUE)
A&MessageBox(CString("Read File Fail :")+filename); return false;
〃利用句柄,得到文件的长度信息 DWORD high32;
DWORD low32=::GetFileSize(hFile,&high32); 〃如果得到长度为0,说明该小文件没有数据,提示没有数据后退出 if(high32=0&&low32=0)
AfidVIessageBox(CString("O File size :")+filename); return false;
〃定义字符凄H且"static std::vector<char> buffer"用于i朱存小文件的数据
DWORD numberO氾ytes;
OVERLAPPED ol;
static std::vector<char> buffer;
buffer ,resize(low32); 〃读取d 、文件的数据到字符数组"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〃把小文件的数据添加到大文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数组中
Itemld++; 〃添加一个小文件后,文件ID号相应加1 Offset+=low32; 〃添加一个小文件后,记录文4快始位置的变量Offset也 要相应增力口
::CloseHandle(hFile); 〃关闭小文件的句柄,返回添加成功信息 return true;
d) 如c)步骤所述,重复调用PutshFile,把各个小文件合成到大文件中。
e) 写一个类,A3dFileldMap,它实现保存"文件名称与文件ID对应表"到文件 "Data.map"中,并实现读取文件"Data.map"的凝:据到类中,并支持用户4是供一个
文件名就可以查询到该文件的文件ID号。 class A3dFileldmap
Public:
〃保存"文件名称与文件ID对应表"的函数 Bool saveFileldMap(CString filename,
std: :list<A3dFileIdMapItem*>&固apList); 〃读取数据文件,4al丈据加载到类的m一filenameldMap数据中 Bool Load(LPCSTR filename); 〃才艮据文件名称,查询文件ID号 Bool getFilelnfo(std::string name,DWORD& id); Private:
Std::map〈std::string, A3dFileldFileNameMapItem *> m一filenameldMap;〃存 放文件名与文件名称映射记录的红黑树
};
〃文4牛头IU居结构
struct A3dFileldMapHeader
10char m一LenFileTag;〃文件标识的长度 char* m一filetag;〃文件标识 int m一version;〃文件版本
int 111一1^1111;//文件名称与文件10号的记录的条数
};
〃保存"文件名称与文件ID对应表,,的函数 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");〃文件标识 fileldMapHeader,m—version=1001; 〃文件版本 fileldMapHeader.m—iNuiTp4dMapList.size();〃^i己录台々^"凄t
〃把文件头写上到文件中,
〃把IdMapList数组中的^i己录写到文件中
FILE* fy = fopen(filename,"wb");〃打开文件,进行只写操作
fWrite(&header->m—LenFileTag,sizeof(header->m—LenFileTag), 1 ,粉;〃写入
文件标识的长度
fWrite(header->m—filetag,sizeof(char),header画〉m一LenFileTag,脉 〃 写入文件 标识
fWrite(&header->m—version,sizeo《header->m—version), 1 ,制; 〃写AJ/反本号 fWrite(&header->m—iNum,sizeof(header-〉m一iNum), 1 ,粉; 〃 写入映射条数〃逐条写入文件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(^));〃关闭文件 return true;
〃读取数据文件,把数据加载到类的m—filenameldMap数据中 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) //读取文件标识的长度
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)〃读取文件标识
goto fail; 〃失M理 〃读取文件版本号
if(fread(&pHeader-〉m—version,sizeof(pHeader->m—version), 1 ,^))=NULL)
goto fail; 〃失败处理 〃读取记录条数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);〃关闭文件 return true; fail:return false;
〃才艮据文件名称,查询文件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,它实现/f絲"文件ID与文件信息对应表"到文件 "Data.index"中,并实现读取文件"Data.index"的数据到类中,并支持用户提供一 个文件ID号就可以查询到该文件的文件信息。 class A3dFilelndex
Public:
〃保存"文件ID与文件信息对应表"的函数 Bool saveFilelndex(CString filename,
std: :list<A3dFileIndexItem*>& IndexList); 〃读取数据文件,4alt据加载到类的m—filenamelndexMap数据中 Bool Load(LPCSTR filename); 〃根据文件ID号,查询文件信息 Bool getFilelnfo(DWORD id,INT64& offset,int& length); Private:
Std::map〈DWORD, A3dFilelndexItem *> m—filenamelndexMap;〃存放文件 ID号与文件信息映射记录的红黑树
〃文件头数据结构
struct A3dFilelndexHeader
char m—LenFileTag; 〃文件标识的长度
char* m—filetag; 〃文件标识
int m—version; 〃文件版本
int mJNum; 〃对应的记录的^l丈};
〃保存"文件ro号与文件信息对应表"的函数
Bool A3dFilelndex ::saveFilelndex(CString filename,std: :list<A3dFileIndexItem*>& IndexList)
A3dFilelndexHeader filelndexHeader;
filelndexHeader,m—LenFileTag=l 6; 〃文件标识的长度 filelndexHeader.m—filetag^ew char [filelndexHeader.m—LenFileTag+1 ]; memset(filelndexHeader.m—filetag,0,filelndexHeader.m—LenFileTag+1); strcpy(filelndexHeader.m—filetag,"IndexTableHeader");〃文件标识 filelndexHeader.m—version: 1001; 〃文件版本
filelndexHeader.m—iNum:IndexListsize();〃文件ID号与文件信息对应 的记录的条数
甜巴文件头写上到文件中 〃把IndexList数组写到文件中
〃方法与A3dFileldmap::saveFileldMap的相关方法完t样,iiLS不再赘述 return true;
}
〃读^Jt据文件,把Jt据加载到类的m—filenameldMap数据中 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) //读取文件标识的长度
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)〃读取文件标识
goto fail; 〃失败处理 〃读取文件版本号
if(fread(&pHeader画〉m—version,sizeof(pHeader->m—version),l,l^))=NULL)
goto fail; //失败处理 〃读取记录条数
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(粉;〃关闭文件 return true; fail:return false;
〃根据文件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模 型,在这种模型中,能实现异步方式的调用。所述异步指在工作者A与工作者B协同 工作的情形下,工作者A向工作者B提交了工作请求后,工作者A不等待工作者B作 出反应就立即离开,并且工作者B在^Vf亍完工作者A提交的一项工作请求后,有办法 通知工作者A该项工作请求已经完成。
在本例中建立一个完成端口队列,实现对大文件的异步存取操作。采用一个类 A3dSingleThreadlocpQueuelmplement来实现完成端口的创建,并实现利用完成端口 , 对大文件异步的进行存耳又访问。
该类暴露给用户的接口主要是WriteFile函数和ReadFile函数,这两个函数可以实 现异步存取大文件的数据。
类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);
〃负责具体实施读出文件中的数据到内存中 void Read(ReadWriteContext* context);
〃负责具体实施写入文件数据到大文件中 void Write(ReadWriteContext* context);
struct ReadWriteContextZ/定义教:才居结构ReadWriteContext
OVERLAPPED ol; 〃完成端口重叠IO
bool bRead; //是否是读取操作的标识
std: :vector<char>* buffer; 〃字符数组,用于存放文件数据
DWORD fileld; 〃文件ID号
int length; 〃文件大小
int icurLength; 〃已完成的文4牛大小
INT64 offset; //偏移位置
A3dlreceiver* receiver; 〃用于回调的通知对象
CRITICAL—SECTION contextLock;
};
public:
A3dSingleThreadlocpQueuelmplement();
〃4巴^lt输入的内存写入到大文件中 virtual bool WriteFile(DWORD fileld, std::vector<char〉* buffer); 〃从大文件中读取某个文件的数据到内存中 virtual void ReadFile(DWORD fileld, int fileLength,A3孤eceiver: receiver);
18};
类的关键实现函数代码如下
才&iL件数据写入到大文件中的函数"WriteFile" ,^#t "fileld"为文件ID号, #|丈"std::vectoKchar>* buffer"为文件数据内存 bool A3dSingleThreadlocpQueuelmplement::WriteFile(DWORD fileld, std::vector<char>* buffer)
ReacTWriteContext* context=new ReadWriteContextO;〃奮r建一-欠i卖 写操作的记录
::EnterCriticalSection(&context隱〉contextLock); context-〉bRead二false;〃才示i口、为写入^)犬态 context->buffer=new std: :vector<char>(buffer->size()); tontext-〉buffeF伞buffer;〃复制文件数据到结构体中 context-〉fileld-fileld;〃复制文件ID号到结构体中
context->length=context-〉buffer-〉size。;〃复制文件大d 、到结构体中 context->icurLength=0; 〃当前已完成的大小为0 context-〉offselK); //偏移位置暂时未知,设为0 ::LeaveCriticalSection(&context-〉contextLock);
\\^6^01^乂化//这个函数具体实现了向大文件进行写入功能
return true;
从大文件中读取某个文件的数据到内存中的函数"ReadFile",参数"fileld"为 文件ID号,"fileLength"为文件长>1信息,^!t "receiver"是用于回调的通 知对象,完成端口一旦完成读取操作,就会通知"receiver"读取完成。
void A3dSingleThreadlocpQueuelmplement::ReadFile(DWORD fileld, int fileLengih.,A3dIReceiver* receiver)
INT64 offset;
〃查找"文件ID与文件信息对应表,,,根据文件的ID得到文件的大 小与起始位置if(m_pFileIndex->getFileInfo(fileId,offset,fileLength))
ReadWriteContext* context=new ReadWriteContext();〃新建一次 读写操作的记录
::EnterCriticalSection(&context-〉contextLock); context->bRead=true; 〃才示识为读耳又^l犬态 context->buffer=new
std:: vector<char>((fileLength+m—dwBlockSize-1 )&~(m—dwBlockSize
隱l)); 〃开辟一段用于^f絲文件数据的内存
context->fileId=fileId; 〃复制文件ID号到结构体中 context->length=fileLength; 〃复制文件大小到结构体中 context->icurLength=0; 〃当前已完成的大小为0 context-〉offset=offset; 〃复制偏移位置到结构体中 contex-〉receivei^receiver;〃复制回调通知对象到结构体中 ::LeaveCriticalSection(&context—〉contextLock);
详见Read函数的说明
〃负责具体实施写入文件数据到大文件中,应该注意的是,该函数是私有函数, 只能由WriteFile函数调用,由于是重叠端口,该函数每次被调用,都向大文件写入小 文件的数提中的一段数據(通常为一个系统分页大小)。用户调用WriteFile函数后就 离开了,完成端口调用了该函数,实现了向大文件写入一段数据后,会判断小文件 是否^卩被写入完成了,如果未完成,完成端口会再次调用该函数,直到小文件已 经写入完成了,这时,通知用户文件写入已经完成。
void A3dSingleThreadlocpQueuelmplement:: Write(ReadWriteContext* context)
::EnterCriticalSection(&context->contextLock);
DWORD highSize;
20DWORD lowSize;
lowSize=GetFileSize(m—hCacheFile,&highSize);〃i^得大文件当前 的长度,高32位长度和#32位长度 memset(&context-〉ol,0,sizeof(context->ol));
(:01^乂1->01.€^561=10\¥8126;//更新结构体的重叠端口的jl^32位偏移 信息
context->ol.OffsetHigh=highSize; 〃更新结构体的重叠端口的高32 位偏移^f言息
if(context)icurLength^Oy/更新结构体的偏移位置信息
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喿作的大小,它为"未完成的大小"与"一个系统分页的大 小"两者之间的小者
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);
〃负责M实施读取大文件中数据到内存中,应该注意的是,该函凄t^私有函数, 只能由ReadFile函数调用,由于是重叠端口,该函数每次被调用,都从大文件读取一 段数据(通常为一个系统分页大小),并^il段数据存放在内存中。用户调用ReadFile 函凄仏就离开了,完成端口调用了该函数,实现了从大文件读取一段数据存放在内 存后,会判断小文件是否4^卩被读取完成了,如果未完成,完成端口会再次调用该 函数,直到小文件数据已经被全部读取完成了,这时,通知用户文件读取已经完成。 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断未完成的大 小是不是已经小于一个系统分页的大小了
nToRead=nLeft>m—dwBlockSize m—dwBlockSize:nLeft;〃决定本次读取操 作的大小,它为"未完成的大小"与"一个系统分页的大小"两者之间的小者
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号与文件信息表"类的指针。分别调用这两 个类的Load函数,就可以,"件中,"tei^两个信息M载到内存中。
例如,需要读取文件"l.bmp ",则可以先调用 "DWORDid;g_pFileIDmap->getFileInfo(std::string("l.bmp",id)"得到"l.bmp"的文件K)号;然 后再调用"INT64 offset;intlength;g_pFileIndexmap->getFileInfo(id,offset,length)"得到 该文件的长度length;接着,设定一个"用于接收完成通知的回调通知者,,对象 "receiver " ; 最后调用 完成端 口 的 函数 A3dSingleThreadlocpQueuelmplement::ReadFile(id,length,receiver)。这样,应用程序就 可以立即离开,等完成端口把文件读取完成,它会把通知给receiver对象,并把文 件的内容发给receiver对象。
如果要保存文件 "l.bmp ", 则可以先调用 "DWORD id;g_pFileIDmap->getFileInfo(std::string("l.bmp",id)"得到"l.bmp"的文件ID号;然 后再把文件的内^f果存到变量"std::vector<char>* buffer"中,调用完成端口的函凄t A3dSingleThreadlocpQueuelmplement::WriteFile(id,buffer)。 il才羊,应用禾呈序t尤可以立 即离开,完成端口会完成写入操作。
综上所述,由于是将大批量的小文件合成一个大文件,还建立了小文件的文件 名和其文件编号的一一对应关系,又建立了小文件的文件编号与其文件信息的对应
关系。所iii:件信息包括小文件在大文件中的位置。这才抖口道要存取的小文件的文 件名就可获得其文件编号,获得了文件编号就可知其文件信息,即其在大文件中的 位置,因此,通过大文件的io接口就可读出小文件的数据,这样大大节约了系统 资源。
权利要求
1、一种大批量文件数据存放方法,其特征在于,包括步骤将所有小文件的数据合并成一个大文件;建立每个小文件的文件名及其文件编号的一一对应关系;建立每个所述文件编号与小文件的文件信息的对应关系,所述文件信息包括所述小文件在所述大文件中的位置。
2、 如权利要求l所述的大批量文件数据存放方法,其特征在于,所述文件信 息还包括所述小文件的文件大小。
3、 一种大批量文件数据读取方法,用于读取按照前述权利要求所述的方法存 放的文件数据,其特征在于,包括步骤冲艮据小文件的文件名来获得所述小文件的文件编号; 根据所述文件编号获得所述小文件的文件信息; 根据所述文件信息荻得所述小文件在大文件中的位置; 根据所述小文件在大文件中的位置,通过所述大文件的10接口实m^f所述小 文件l封居的读取。
全文摘要
本发明公开一种大批量文件数据存取方法,包括将所有小文件的数据合并成一个大文件;建立每个小文件的文件名及其文件编号的一一对应关系;建立每个所述文件编号与小文件的文件信息的对应关系,所述文件信息包括所述小文件在所述大文件中的位置。相应地,本发明还公开一种大批量文件数据读取方法,用于读取按照本发明的存放方法存放的文件数据,包括步骤根据小文件的文件名来获得所述小文件的文件编号;根据所述文件编号获得所述小文件的文件信息;根据所述文件信息获得所述小文件在大文件中的位置;根据所述小文件在大文件中的位置,通过所述大文件的IO接口实现对所述小文件数据的读取。采用本发明的技术方案能够节约系统资源。
文档编号G06F17/30GK101452465SQ20071019900
公开日2009年6月10日 申请日期2007年12月5日 优先权日2007年12月5日
发明者易国真 申请人:高德软件有限公司
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1