需求只是想实现文件中任意位置删除或添加一个或多个字节。开始以为这个挺简单的,于是打开VS来就开干,先用FILE*试试,结果发现,只要设定了"a+"的打开方式,fseek是无法移动到任意位置添加的,除非把文件全读到缓冲区去,但是如果文件有几个G或几十个G的话,那将会是一个漫长的时间。后来想到用Win32 API CreateFile,发现只用CreateFile还是无法解决问题,于是就找到了另一个API函数 CreateFileMapping...就写下了下列代码
/////////////////////////////////////////////////////////
#include<IOSTREAM>
#include<WINDOWS.H>
using namespace std;
int main()
{
HANDLE hFile = CreateFile(
"C:\\1.txt",
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (hFile == INVALID_HANDLE_VALUE)
{
cout<<"创建文件对象失败,错误代码:"<<GetLastError()<<endl;
return 0;
}
HANDLE hFileMap = CreateFileMapping(hFile,NULL,PAGE_READWRITE,0,0,NULL);
if (hFileMap == NULL)
{
cout<<"创建文件映射对象失败,错误代码:"<<GetLastError()<<endl;
return 0;
}
SYSTEM_INFO SysInfo;
GetSystemInfo(&SysInfo);
DWORD dwGran = SysInfo.dwAllocationGranularity;
DWORD dwFileSizeHigh;
__int64 qwFileSize = GetFileSize(hFile,&dwFileSizeHigh);
qwFileSize |= (((__int64)dwFileSizeHigh) << 32);
CloseHandle(hFile);
__int64 qwFileOffset = 0;//文件指针位置
DWORD dwBlockBytes = dwGran;//每节文件的最大长度
while (qwFileSize > 0)
{
//映射视图
if (qwFileSize < dwGran) //如果文件长度小于系统分配的最大长度
dwBlockBytes = (DWORD)qwFileSize;
LPBYTE lpbMapAddress = (LPBYTE)MapViewOfFile(
hFileMap,
FILE_MAP_ALL_ACCESS,
(DWORD)(qwFileOffset >> 32),
(DWORD)(qwFileOffset & 0xFFFFFFFF),
dwBlockBytes
);//取出字节流指针
if (lpbMapAddress == NULL)
{
cout<<"映射文件映射失败,错误代码:%d"<<GetLastError()<<endl;
}
cout<<lpbMapAddress<<endl;
//撤消文件映像
UnmapViewOfFile(lpbMapAddress);
qwFileOffset += dwBlockBytes;
qwFileSize -= dwBlockBytes;
}
CloseHandle(hFileMap);
cout<<"完成"<<endl;
system("pause");
return 0;
};
/////////////////////////////////////////////
从代码可以看出
文件映射的原理是把文件物理地址映射到系统的空间地址中去。
文件是一节一节的,每节大小是SysInfo.dwAllocationGranularity 一般的机器是64KB俱体跟
硬件有关。
于是,我们用了一个while,可以把所有字节,通过CreateFileMapping抛给lpbMapAddress字节指针,这样可以取到数据,但这里产生了一个疑问,因为我要的是在指定位置添加/删节除一个或多个字节数据,这样就会改变文件的长度,如果用内存操作的话,那还是要用循环把内存每节都向后移动。。。
但是经过疯狂的百度后,绝大多数人都是推荐这种操作方法,但他们并没有任何一个人给出俱体的操作步骤,鄙人只能操作到这一步,就操作不下去了。。所以特来C++吧求助。
希望能够得到有用的回复,谢谢。
/////////////////////////////////////////////////////////
#include<IOSTREAM>
#include<WINDOWS.H>
using namespace std;
int main()
{
HANDLE hFile = CreateFile(
"C:\\1.txt",
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (hFile == INVALID_HANDLE_VALUE)
{
cout<<"创建文件对象失败,错误代码:"<<GetLastError()<<endl;
return 0;
}
HANDLE hFileMap = CreateFileMapping(hFile,NULL,PAGE_READWRITE,0,0,NULL);
if (hFileMap == NULL)
{
cout<<"创建文件映射对象失败,错误代码:"<<GetLastError()<<endl;
return 0;
}
SYSTEM_INFO SysInfo;
GetSystemInfo(&SysInfo);
DWORD dwGran = SysInfo.dwAllocationGranularity;
DWORD dwFileSizeHigh;
__int64 qwFileSize = GetFileSize(hFile,&dwFileSizeHigh);
qwFileSize |= (((__int64)dwFileSizeHigh) << 32);
CloseHandle(hFile);
__int64 qwFileOffset = 0;//文件指针位置
DWORD dwBlockBytes = dwGran;//每节文件的最大长度
while (qwFileSize > 0)
{
//映射视图
if (qwFileSize < dwGran) //如果文件长度小于系统分配的最大长度
dwBlockBytes = (DWORD)qwFileSize;
LPBYTE lpbMapAddress = (LPBYTE)MapViewOfFile(
hFileMap,
FILE_MAP_ALL_ACCESS,
(DWORD)(qwFileOffset >> 32),
(DWORD)(qwFileOffset & 0xFFFFFFFF),
dwBlockBytes
);//取出字节流指针
if (lpbMapAddress == NULL)
{
cout<<"映射文件映射失败,错误代码:%d"<<GetLastError()<<endl;
}
cout<<lpbMapAddress<<endl;
//撤消文件映像
UnmapViewOfFile(lpbMapAddress);
qwFileOffset += dwBlockBytes;
qwFileSize -= dwBlockBytes;
}
CloseHandle(hFileMap);
cout<<"完成"<<endl;
system("pause");
return 0;
};
/////////////////////////////////////////////
从代码可以看出
文件映射的原理是把文件物理地址映射到系统的空间地址中去。
文件是一节一节的,每节大小是SysInfo.dwAllocationGranularity 一般的机器是64KB俱体跟
硬件有关。
于是,我们用了一个while,可以把所有字节,通过CreateFileMapping抛给lpbMapAddress字节指针,这样可以取到数据,但这里产生了一个疑问,因为我要的是在指定位置添加/删节除一个或多个字节数据,这样就会改变文件的长度,如果用内存操作的话,那还是要用循环把内存每节都向后移动。。。
但是经过疯狂的百度后,绝大多数人都是推荐这种操作方法,但他们并没有任何一个人给出俱体的操作步骤,鄙人只能操作到这一步,就操作不下去了。。所以特来C++吧求助。
希望能够得到有用的回复,谢谢。