现在的位置: 首页 > 综合 > 正文

《Windows核心编程》—文件操作

2012年05月01日 ⁄ 综合 ⁄ 共 3819字 ⁄ 字号 评论关闭

Windows提供了一类API来读、写和管理磁盘文件。

使用API函数读写文件时,首先要使用CreateFile函数创建文件对象,调用成功会返回文件句柄。我们以此句柄为参数调用ReadFileWriteFile函数,进行实际的读写操作;最后调用CloseHandle函数关闭不再使用的文件对象句柄。

 

1)打开和关闭文件:

CreateFile是一个功能强大的函数,Windows下的底层设备几乎都由它打开。它可以创建或打开文件、目录、物理磁盘、控制台缓冲区、油槽或管道等:

HANDLE CreateFile(

         LPCTSTR lpFileName,  //要创建或打开的对象的名称

         DWORD dwDesiredAccess, //文件的存取方式

         DWORD dwShareMode,               //共享属性

         LPSECURITY_ATTRIBUTES lpSecurityAttributes,      //安全属性

         DWORD dwCreationDisposition,                //文件存在或不存在时系统采取的行动

         DWORD dwFlagsAndAttributes,         //新文件的属性

         HANDLE hTemplateFile       //一个文件模板的句柄

         );

lpFileName—如果是打开文件,直接指定文件名称即可;如果操作对象是第一个串口,则指定“COM1”为文件名,然后就可以像操作文件一样操作串口了;如果要打开本地电脑上的一个服务,要以//./服务名称为文件名,其中”.”代表本地机器;如果要打开网络中其他主机的文件,则以//主机名/共享目录名/文件名为文件名。

dwDesiredAccessGENERIC_READ(只读)GENERIC_WRITE(只写)、两者组合。

dwShareMode—表示文件打开后是否允许其他代码以某种方式再次打开这个文件,可以是下面的组合:

         0—不允许文件再被打开。C语言中的fopen函数就是这种方式;

         FILE_SHARE_DELETE—允许其他程序代码删除文件;

         FILE_SHARE_READ—允许其他程序代码以读方式打开文件;

         FILE_SHARE_WRITE—允许其他程序代码以写方式打开文件;

dwCreationDisposition—指定当文件已存在或不存在时系统采取的动作:

         CREATE_ALWAYS—创建新文件,若文件存在,则覆盖它,清除存在的属性;

         CREATE_NEW—创建新文件。若文件存在,函数执行失败;

         OPEN_ALWAYS—如果文件存在则打开它,不存在则创建新文件;

         OPEN_EXISTING—打开存在的文件。若文件不存在,函数执行失败;

         TRUNCATE_EXISTING—打开文件并将文件截断为0,当文件不存在时函数执行失败。

dwFlagsAndAttributes—指定新建文件属性和标志,可以是以下各项的组合:

         FILE_ATTRIBUTE_ARCHIVE—标记归档属性;

         FILE_ATTRIBUTE_HIDDEN—标记隐藏属性;

         FILE_ATTRIBUTE_READONLY—标记只读属性;

         FILE_ATTRIBUTE_SYSTEM—标记系统属性;

                FILE_ATTRIBUTE_TEMPORARY—临时文件,操作系统会尽量把所有文件的内容保持在内存中以加快存取速度。使用完后要尽快将它删除。

         FILE_FLAG_DELETE_ON_CLOSE—文件关闭后系统立即自动删除它;

         FILE_FLAG_OVERLAPPED—使用异步读写文件的方式;

         FILE_FLAG_WRITE_THROUGH—系统不会对文件使用缓冲,文件的任何改变都会被系统立即写入硬盘。

hTemplateFile—指定一个文件模板句柄。系统会复制文件模板的所有属性到当前创建的文件中。

 

打开或创建文件成功时,函数返回文件句柄,失败时返回INVALID_HANDLE_VALUE

 

2)移动文件指针:

SetFilePointer函数:系统为每个打开的文件维护一个文件指针,指定对文件的下一个读写操作从什么位置开始。随着数据的读出或写入,文件指针也随之移动。当文件刚被打开时,文件指针处于文件的头部。有时候需要随机读取文件内容,这就需要先调整文件指针:

DWORD SetFilePointer(

         HANDLE hFile,                //文件句柄

         LONG lDistanceToMove,    //要移动的距离

         PLONG lpDistanceToMoveHigh,        //移动距离的高32位,一般位置为NULL

         DWORD dwMoveMethod           //移动的模式

         );

dwMoveMethod参数指明从什么地方开始移动:

         FILE_BEGIN—开始移动的位置为0,即从文件头部开始移动;

         FILE_CURRENT—开始移动位置是文件指针的当前值;

         FILE_END—开始移动位置是文件的结尾,即从文件尾开始移动。

文件指针也可以移动到所有数据后面,比如现在文件长度是200KB,但可以成功地将文件指针移动到1000KB的位置。这样做可以达到扩展文件长度的目的。

SetEndOfFile函数就可以达到截断或者扩展文件的功能。该函数移动指定文件的结束标志(EOF)到文件指针指向的位置。如果文件扩展,旧的EOF位置和新的EOF位置间的内容是未定义的:

BOOL SetEndOfFile(HANDLE hFile);

截断或者扩展文件时,要首先调用SetFilePointer移动文件指针,然后再调用SetFilePointer函数设置新的文件指针位置为EOF

 

3)读写文件:

ReadFileWriteFile函数既可以同步读写文件,也可以异步读写文件;而函数ReadFileExWriteFileEx只能异步读写文件。

BOOL ReadFile(

         HANDLE hFile,                //文件句柄

         LPVOID lpBuffer,  //指向一个缓冲区,函数会将读出的数据返回到这里

         DWORD nNumberOfBytesToRead,   //要求读入的字节数

         LPDWORD lpNumberOfBytesRead,  //指向一个DWORD类型的变量,用于返回实际读入的字节数

         LPOVERLAPPED lpOverlapped  //一般设为NULL

         );

 

BOOL WriteFile(

         HANDLE hFile,                //文件句柄

         LPVOID lpBuffer,  //指向一个缓冲区,包含了要写入文件的数据

         DWORD nNumberOfBytesToWrite, //要求写入的字节数

         LPDWORD lpNumberOfBytesWritten,     //指向一个DWORD类型的变量,用于返回实际写入的字节数

         LPOVERLAPPED lpOverlapped  //一般设为NULL

         );

使用WriteFile写文件时,写入的数据通常被Windows暂存在内部的高速缓存中,等合适的时候再一并写入磁盘。可以使用FlushFileBuffers函数来强制系统清空缓冲区:

BOOL FlushFileBuffers(HANDLE hFile);

 

4)锁定文件:

当我们对文件数据的一致性要求较高时,为了防止程序在写入过程中其他进程刚好在读取写入区域的数据,可以对已打开文件的某个部分加锁,加锁和解锁的函数分别是LockFileUnlockFile

BOOL LockFile(

         HANDLE hFile,       //文件句柄

         DWORD dwFileOffsetLow,         //加锁的开始位置

         DWORD dwFileOffsetHigh,

         DWORD nNumberOfBytesToLockLow,    //加锁区域的大小

         DWORD nNumberOfBytesToLockHigh

         );

 

BOOL UnlockFile(

         HANDLE hFile,       //文件句柄

         DWORD dwFileOffsetLow,         //解锁的开始位置

         DWORD dwFileOffsetHigh,

         DWORD nNumberOfBytesToLockLow, //解锁区域的大小

抱歉!评论已关闭.