HANDLE CreateFile(
LPCTSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile
)
参数解析:
lpFileName:需要创建或者打开的文件名字
dwDesiredAccess:文件的打开方式,GENERIC_READ(只读), GENERIC_WRITE(只写), GENERIC_READ | GENERIC_WRITE(读写)
dwShareMode:文件的共享方式,如:FILE_SHARE_DELETE, FILE_SHARE_READ, FILE_SHARE_WRITE
lpSecurityAttributes:文件的安全属性,通常为空
dwCreationDisposition:文件的访问方式,如:CREATE_ALWAYS, CREATE_NEW, OPEN_ALWAYS, OPEN_EXISTING, or TRUNCATE_EXISTING(只能是其中一种,不能组合使用)
dwFlagsAndAttributes:文件属性和标志
hTemplateFile:模板文件句柄
2、 创建文件内存映射(CreateFileMapping),如下:
HANDLE WINAPI CreateFileMapping(
_In_ HANDLE hFile,
_In_opt_ LPSECURITY_ATTRIBUTES lpAttributes,
_In_ DWORD flProtect,
_In_ DWORD dwMaximumSizeHigh,
_In_ DWORD dwMaximumSizeLow,
_In_opt_ LPCTSTR lpName
)
参数解析:
hFile:需要创建文件内存映射基春大的文件句柄
lpAttributes:安全属性指针
flProtect:文件内存映射访问模式
dwMaximumSizeHigh:内存映射大小的高32位
dwMaximumSizeLow:内存映射大小的低32位
lpName:内存映射的名字
3、 获得系统分配粒度(GetSystemInfo),如下:
void WINAPI GetSystemInfo(
_Out_ LPSYSTEM_INFO lpSystemInfo
)
参数解析:
lpSystemInfo:SYSTEM_INFO结构指针
4、 文件内存映射视图(MapViewOfFile)
LPVOID WINAPI MapViewOfFile(
_In_ HANDLE hFileMappingObject,
_In_ DWORD dwDesiredAccess,
_In_ DWORD dwFileOffsetHigh,
_In_ DWORD dwFileOffsetLow,
_In_ SIZE_T dwNumberOfBytesToMap
)
参森举数解析:
hFileMappingObject:文件内存映射搏竖句柄
dwDesiredAccess:访问方式,如FILE_MAP_ALL_ACCESS、FILE_MAP_COPY等
dwFileOffsetHigh:文件偏移大小高位
dwFileOffsetLow:文件偏移大小低位
注意:文件偏移必须是系统粒度的整数倍
dwNumberOfBytesToMap:映射多少数据进视图
5、 撤销文件内存映射视图(UnmapViewOfFile)
BOOL WINAPI UnmapViewOfFile(
_In_ LPCVOID lpBaseAddress
)
参数解析:
lpBaseAddress:文件视图指针
三、使用方法
1、 使用CreateFile创建/打开一文件,这个文件对象标识了磁盘上将要用作内存映射文件的文件。
2、 使用CreateFileMapping函数来创建一个文件映射内核对象,告诉系统文件的尺寸以及访问文件的方式。
3、 使用MapViewOfFile函数负责通过系统的管理而将文件映射对象的全部或部分映射到进程地址空间。
4、 通过UnmapViewOfFile完成从进程的地址空间撤消文件数据的映像、通过CloseHandle关闭前面创建的文件映射对象和文件对象。
四、使用举例
功能:在一个大文件(文件名BigFile.txt)中,查找一字符串”End”。实现根据字符串"End"将文件截断的功能。
代码工程名IOTest.sln:
详细代码见BigFileFun.h、BigFileFun.cpp
调用代码见IOTest.cpp中_tmain函数
在C#中读取20GB以上的大文件,建议使用流(Stream)来读取,以避免一次性加载整个文件到内存中而导致内存不足的问题。
以下是一种使用流来读取大文件的示例代码:
using (FileStream fs = new FileStream(@"C:\path\to\large\file.txt", FileMode.Open, FileAccess.Read))
{
using (BufferedStream bs = new BufferedStream(fs))
{
using (StreamReader sr = new StreamReader(bs))
{
string line
while ((line = sr.ReadLine()) != null)
{
// 处理每一行数据的逻辑
}
}
}
}
在这个代码示例中,我们使用了三个流对象:
FileStream:用于打开大文件并将其作为输入流
BufferedStream:用于加快数据的读取速度,通粗手过使用一个内部缓岩磨嫌存来减少对硬盘的读取次数
StreamReader:用于按行读取文本数据
在while循环中,我们可以处理每一行数据的逻辑。由于只读取了一行数据,因此内存占用较小,可以避免因为文件过大导致内存溢出的问题。
需要注意的是,在处理大文件时,为了保证性能,最好游基使用异步读取方式。这可以通过将StreamReader对象的ReadLine方法替换为异步版本ReadLineAsync来实现。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)