文件设备

16.2使用文 件设备

16.2.1定位文件指针:

当CreateFile返回一个文件句柄时,系统给句柄关联了一个文件指针,这个文件指针给出了文件内部一个64位偏移量, 下次的同步读写将在此处进行。开始时这个指针被设置成0,所以在你调用CreateFile返回一个文件句柄后,立即调用ReadFile,你将从文件的 偏移0处开始读。如果你读取100字节的数据到内存中,系统将会更新与文件句柄关联的指针位置,使得在下一次调用ReadFile时,从文件的第101字 节开始读取文件的数据。

举例说明:

HANDLE hFile = CreateFile(……);

ReadFile(hFile,lpBuffer,100,&dwBytesRead,NULL); 是从指针为0处开始读

WriteFile(hFile,lpBuffer,100,&dwBytesWrite,NULL); 是从指针为100处开始写

在这 段代码中,文件的前100个字节用于执行ReadFile函数,而WriteFile是从文件的第101个字节开始的,这是因为在执行完ReadFile 后,与文件关联的指针已经被更新为100了,所以在调用函数WriteFile时,是从文件的第100字节开始写的。

如 果是打开同一文件多次的话,就与上面的情况不一样了,每打开一次文件,与文件句柄关联的指针都会被设置成0,所以如果这样写这段代码,

HANDLE hFileA = CreateFile(“MyFile”,…);

HANDLE hFileB = CreateFile(“MyFile”,…);

ReadFile(hFileA,lpBuffer,100,&dwBytesRead,NULL);是从指针为0处开始读

WriteFile(hFileB,lpBuffer,100,&dwBytesWrite,NULL);是从指针为0处开始写

另外介绍一个函数SetFilePointer,

DWORD SetFilePointer(HANDLE hFile,LONG lDistanceToMove,

PLONG lpDistanceToMoveHigh,DWORD dwMoveMethod);

参数说明:

lDistanceToMove告诉系统你想要移动指针多少个字节。注意,你指定的值是增加到指针的当前值,也就是说,你传递给该参 数负值的话,等同于将指针向后移。

LpDistanceToMoveHigh: 当你移动指针的范围是正负2GB以内,那么参数lpDistanceToMoveHigh设置为NULL。如果你移动指针的范围是正负180GB,那么你 需要在这个值的高32位传递给该参数。实际上,不能直接将这个值的高32位传递给该参数,而是将这个值的高32的地址传递给参数 lpDistanceToMoveHigh。这样传递的原因是,SetFilePointer函数返回文件指针以前的位置。如果你感兴趣的是这个指针的低 32位,那么SetFilePointer直接返回这个值。如果你对指针的高32位也感兴趣,那么SetFilePointer在返回前填充参数 lpDistanceToMoveHigh的值。

DwMoveMethod: 它告诉SetFilePointer如何解释参数lDistanceToMove 和lpDistanceToMoveHigh,可以传递给该参数三个值,它们是:

说明

FILE_BEGIN

文件指针变成由两 个DistanceToMove参数指定的无符号值

FILE_CURRENT

文件指针被加上由 两个参数DistanceToMove指定的有符号值

FILE_END

文件指针变成由文 件的字节数加上由两个参数DistanceToMove指定的有符号值

如果函数SetFilePointer没有改变文件的指针,它将返回 0xFFFFFFFF,lpDistanceToMoveHigh的缓冲区将包含NULL。最好调用GetError,看GetError是否返回 NO_ERROR,来验证SetFilePointer是否成功。

16.2.2设置文件尾:

BOOL SetEndOfFile(HANDLE hFile);该函数改变文件长度,例如,你想强制一个文件的长度为1024字节,你可以这样做,

HANDLE hFile = CreateFile(…);

SetFilePointer(hFile,1024,NULL,FILE_BEGIN);

SetEndOfFile(hFile);

16.2.3加锁和解锁文件的区域:

1. 文件的加锁和解锁只影响文件的部分区域,使用函数LockFile来锁定一个文件的某一块区域,

BOOL LockFile(HANDlE hFile,DWORD dwFileOffsetLow,

DWORD dwFileOffsetHigh,DWORD cbLockLow,DWORD cbLockHigh);

参 数说明:

hFile是要锁定的文件句柄。

DwFileOffsetLow和 dwFileOffsetHigh指定你想开始锁定的文件的64位偏移量。

DwLockLow和 dwLockHigh指定你想锁定的字节数。

举例 说明:假如你想锁定数据库中的第一百条记录,

LockFile(hFile,sizeof(CUSTOMER_RECORD)*(100 - 1),0,

sizeof(CUSTOMER_RECORD),0);

如 果锁定成功LockFile将返回TRUE。当文件的一个区域被锁时,所有其它想读写该区域的进程都将会失败。

注意:锁定的区域超过当前的文件尾也是合法的,例如:在你在数据库中增加新记录时。可以锁定超过文件尾的一块区域,之后把新客户数据 写到这个区域里。

还有一点需要注意,你锁定的区域不能包括已经锁定的区域。举例说明:看如下这两个对LockFile函数的调用,第一个会成功调用,第二个会失败,原因是第二LockFile锁定的区域已经包括在第一个 LockFile锁定的区域内了,

LockFile(hFile,sizeof(CUSTOMER_RECORD)*(100 - 1),0,

sizeof(CUSTOMER_RECORD),0);// 锁定第100条记录

LockFile(hFile,sizeof(CUSTOMER_RECORD)*(100 - 2),0,

2 * sizeof(CUSTOMER_RECORD),0);//锁定第99条合第100条记录

很明显,在第二次对LockFile的调用时,也锁定了第100条记录,而在第一调用 时,LockFile已经锁定了这条记录,所以第二次对LockFile的调用将失败。

2.在对锁定的区域操作结束后,需要使用UnLockFile来释放这块锁定的区域,

BOOL UnLockFile(HANDLE hFile,DWORD dwFileOffsetLow,

DWORD dwFileOffsetHigh,DWORD dwUnLockLow,DWORD dwUnLockHigh);

UnLockFile与函数LockFile的参数相同,返回值也一样。当你解锁一个区域时, 必须与加锁一个区域时相同。举例说明:

LockFile(hFile,sizeof(CUSTOMER_RECORD)*(100 - 1),0,

sizeof(CUSTOMER_RECORD),0); 锁定第100条记录

LockFile(hFile,sizeof(CUSTOMER_RECORD)*(100 - 2),0,

sizeof(CUSTOMER_RECORD),0);// 锁定批99条记录

下面解锁这两个锁定区域,

UnLockFile(hFile,sizeof(CUSTOMER_RECORD)*(100 - 1),0,

sizeof(CUSTOMER_RECORD),0);

UnLockFile(hFile,sizeof(CUSTOMER_RECORD)*(100 - 1),0,

sizeof(CUSTOMER_RECORD),0);

注意:解锁时,必须与加锁时相同,不能用一个UnLockFile把前面两个LockFile 加锁的区域一次解锁,加锁与解锁要一 一对应。

还有一点需要注意:在关闭一个文件或终结进程前一定要解锁全部加锁区域。

3.函数LockFileEx:

LockFileEx 比函数LockFile多了两个功能,一、它在锁定文件的某个区域时,可以设定属性以使其它进程可以读该锁定区域,二、可以告诉LockFileEx直接 锁定文件成功后返回。第二个功能比起LockFile要好多了,因为当调用LockFile时,如果想锁定的文件区域已经被另一个线程锁定了,那么 LockFile会立即返回,但是你可以告诉LockFileEx一直等到获得文件为止才返回。下面列出函数LockFileEx的定义,

BOOL LockFileEx(HANDLE hFile,DWORD dwFlags,

DWORD dwReserved,DWORD nNumberOfBytesToLockLow,

DWORD nNumberOfBytesToLockHigh,

LPOVERLAPPED lpOverLapped);

LockFileEx使用 OVERLAPPED结构中的成员Offset和OffsetHigh。

下面列出结构 OVERLAPPED的定义:

typedef struct _OVERLAPPED{

DWORD Internal;

DWORD InternalHigh;

DWORD Offset;

DWORD OffsetHigh;

HANDLE hEvent; //事件内核对象

}OVERLAPPED,*LPOVERLAPPED;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值