1. Win32 API就是系统调用,偏向底层,像C\C++中的很多函数,比如malloc还有很多文件操作函数都是用Win32 API实现的;
2. 创建文件映射:
a. 同样也是将硬盘中的文件映射到内存,但是没有FILE *指针指向这片内存了,而是只能用一个void *指针来代替,由此可以看到Win32 API对类型的敏感级别非常低,更加偏向底层,偏向硬件;
b. 句柄就是指void *指针,其定义就是typedef void *HANDLE,之所以叫句柄,其表面意思就是指一句句话组成的模块的首地址,至于这些话,可以是一个结构体,也可能是一段函数,可以是任何语句,具体实现什么功能不确定,因此将句柄定义为void *指针;
c. 使用CreateFile函数将文件映射到内存,并返回内存中文件的句柄(即内存区域首地址);
d. CreateFile的参数(共有7个):
*1. const void *,即文件路径名;
*2. DWORD字节型数据(4字节,表示4字节数据,用法和int类似,即typedef unsigned long DWORD),表示读写模式;
*3. DWORD,共享模式;
*4. 指向安全属性的指针,这里先不做研究,使用时该参数传NULL即可;
*5. DWORD,指明文件的创建方式;
*6. DWORD,文件的属性,隐藏、系统还是正常等;
*7. HANDLE,用于复制文件的句柄,再次先不讨论,使用时该参数传NULL即可;
e. 读写模式:
i. 这只指明读还是写,而不指明文件如何打开(创建、截断等);
ii. 如何打开的内容由第5个参数决定,注意和前面所讲的文件操作的区别(之前都是将文件的读写和创建放在一个参数中);
iii. 三种参数:
*1. 0:表示既不能读也不能写,仅仅就这么打开一下,啥事儿都不能干;
*2. GENRIC_READ:只能读;
*3. GNERIC_WRITE:只能写;
*4. 将*2.和*3.连用可以既能读又能写;
f. 共享模式(四种):
*1. 0:独占,不共享;
*2. FILE_SHARE_READ:只共享读;
*3. FILE_SHARE_WRITE:只共享写;
*4. FILE_SHARE_DELETE:至共享删除文件;
*5. 后三种模式可以进行组合;
g. 创建和打开模式:
i. 创建模式(两种):
*1. CREATE_NEW:如果文件不存在就创建,如果已存在则失败;
*2. CREATE_ALWAYS:如果文件不存在就创建,如果已存在就截断并将原有属性清空;
ii. 打开模式(三种):
*1. OPEN_EXISTING:如果文件存在就打开但不截断,如果文件不存在就失败,即只打开存在的文件;
*2. OPEN_ALWAYS:如果文件存在就打开,如果文件不存在就使用CREATE_NEW创建;
*3. TRUNCATE_EXISTING:必须和OPEN_EXISTING合用,如果文件存在就打开并截断,如果文件不存在就失败;
h. 文件标记和属性:
i. 文件属性(五种):
*1. 都是以FILE_ATTRIBUTE_作为前缀:
*2. ARCHIVE:归档;
*3. NORMAL:正常,即无属性设置,该属性只有在单独使用时才有效;
*4. HIDDEN:隐藏;
*5. READONLY:只读;
*6. SYSTEM:表示这是一个系统文件,将受到保护;
ii. 标记(这里只介绍一种):
FILE_FLAG_WRITE_THROUGH:指示系统不经过缓存就将文件读入硬盘;
3. 使用WriteFile写入文件:
a. 参数也是和之前的Write、Read函数大同小异;
b. 只不过之前的函数都是将(即C语言的fread和fwrite)文件指针作为最后一个参数,而这里是将文件句柄作为第一个参数;
c. 第二个参数就是内存缓冲区指针,和之前介绍过的函数的内存缓冲区指针一样,都是const void *类型的;
d. 第三个参数是想写入的字节数,DWORD类型;
e. 第四个参数是实际写入的字节数,这个参数将作为一个输出参数,而不是作为函数返回参数,由于API没有引用操作,因此只能传一个DWORD变量指针进去,可以实现函数调用多外部变量的值的修改;
d. 第五个参数是一个异步结构体指针,这里不做研究,使用时该参数传NULL即可;
e. 程序示例:
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
// initialize MFC and print and error on failure
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: change error code to suit your needs
cerr << _T("Fatal Error: MFC initialization failed") << endl;
nRetCode = 1;
}
else
{
// TODO: code your application's behavior here.
char pBuf[100];
memset(pBuf, 0, 100);
HANDLE hFile = CreateFile("M:\\Test Programs\\VC6.0\\Test.txt",
GENERIC_WRITE,//只写的方式
0,//独占
NULL,//无安全属性
CREATE_ALWAYS,//如果文件不存在则创建,如果文件已存在就截断并清空原有属性
FILE_ATTRIBUTE_NORMAL,//属性为正常
NULL//无文件复制属性
);
DWORD dwWrites = 0;//定义一个接受实际写入字节数的计数变量
for ( int i = 1 ; i <= 20 ; i++ ) {
sprintf(pBuf, "Line %d\r\n", i);
WriteFile(hFile, pBuf, strlen(pBuf), &dwWrites, NULL);
}
CloseHandle(hFile);//注意,是CloseHandle而不是CloseFile,因为接受文件内存映射的是一个普通的句柄
hFile = NULL;//一旦将内存映射区释放掉就要将指针置空,逢野必空!
}
return nRetCode;
}
4. 使用ReadFile读取文件:
a. ReadFile和WriteFile的参数一模一样,只不过pBuf是void *类型的而已;
b. 在打开文件后需要用API的GetFileSize函数获取文件的字节数,第一个参数是文件句柄,而第二个参数是一个输出参数,他会将文件字节数(是DWORD类型)的高2位字节中的数据返回,因此传的是一个DWORD的指针,这里我们不需要返回值的高2位字节中的内容,只需要返回文件总字节长度就行了,因此这项传NULL就行了;
c. 程序示例:
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
// initialize MFC and print and error on failure
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: change error code to suit your needs
cerr << _T("Fatal Error: MFC initialization failed") << endl;
nRetCode = 1;
}
else
{
// TODO: code your application's behavior here.
HANDLE hFile = CreateFile("M:\\Test Programs\\VC6.0\\Test.txt",
GENERIC_READ,//写模式
0,//独占
NULL,//无安全属性
OPEN_EXISTING,//只打开已存在的文件
FILE_ATTRIBUTE_NORMAL,//文件属性为正常
NULL//无文件复制属性
);
int iFileLen = GetFileSize(hFile, NULL);//获得文件的大小,其实就是测量内存块的大小
char *pBuf = new char [iFileLen + 1];
memset(pBuf, 0, iFileLen + 1);
DWORD dwReads;//定义一个接受实际读入字节数的计数变量
ReadFile(hFile, pBuf, iFileLen, &dwReads, NULL);
printf("%s", pBuf);
CloseHandle(hFile);//释放文件的内存映射
hFile = NULL;
delete [] pBuf;
pBuf = NULL;
}
return nRetCode;
}