Windows 文件操作 — 创建和读写

1 打开和关闭文件
打开文件使用CreateFile 用法如下

invoke CreateFile,lpFileName,dwDesiredAccess,dwShareMode,lpSecurityAttributes,dwCreationDisposition,dwFlagsAndAttributes,hTemplateFile

各参数含义如下:
lpFileName:指向存放有文件名的缓冲区,文件名是以0结尾的字符串,字符最大长度为MAX_PATH(windows.inc中为260),可以打开多种对象,包括:控制台(Consoles),通信设备(Communications resources)-包括串口等,目录(Directories)和文件(Files),邮件槽(Mailslots),管道(Pipes)

dwDesiredAccess参数是存取方式,可以取的值有两个
GENERIC_READ 表示读取文件数据
GENERIC_WRITE 表示写数据
如果要读写数据,要同时指定这两个标志

dwShareMode参数是共享属性,表明文件被打开后是否允许其它进程再次打开文件, 可以取的值有四个
0:不允许文件再被打开
FILE_SHARE_DELETE:允许其它进程同时对文件进行删除
FILE_SHARE_READ:允许其它进程以读方式打开文件
FILE_SHARE_WRITE:允许其它进程同时以写方式打开文件

lpSecurityAttributes参数为安全属性,指定文件句柄是否可以被子进程继承,为NULL表明无法被继承,否则要将参数指向一个SECURITY_ATTRIBUTES结构,该结构定义如下

SECURITY_ATTRIBUTES STRUCT
nLength DWORD ? ;本结构的长度
lpSectrityDescriptor DWORD ?
bInheritHandle DWORD ? ;是否允许继承
SECURITY_ATTRIBUTES ENDS

将nLength设置为结构的长度,将bInheritHandle设置为TRUE就可以使句柄能够被子进程继承

dwCreationDisposition参数用来设置文件已经存在或不存在时系统采取的动作,在这里可以指定函数要执行的功能是创建还是打开.共有5个值:
CREATE_NEW:创建新文件,如果文件以存在函数会返回失败
CREATE_ALWAYS:创建新文件,如果文件以存在则清除原文件
OPEN_EXISTING:打开存在的文件,当文件不存在时函数返回失败
OPEN_ALWAYS:如果文件以存在,则打开,不存在则创建新文件
TRUNCATE_EXISTING:打开文件并将文件截断为零,当文件不存在时,返回失败

dwFlagsAndAttributes参数用来指定新建文件的属性,可以有10个值
FILE_ATTRIBUTE_NORMAL:普通文件,设置这个属性时其他属性都不会生效
FILE_ATTRIBUTE_ARCHIVE:设置归档属性
FILE_ATTRIBUTE_HIDDEN:设置隐藏属性
FILE_ATTRIBUTE_READONLY:设置只读属性
FILE_ATTRIBUTE_SYSTEM:设置系统属性
FILE_ATTRIBUTE_TEMPORARY:临时文件,系统会尽量把文件内容保持在内存中,以加快存取速度,程序在不使用它时会尽快删除它
此外还可以指定对文件操作的方式
FILE_FLAG_WRITE_THROUGH:使用WriteThrough模式,系统不会对文件使用缓存.
FILE_FLAG_OVERLAPPED:使用异步文件操作模式
FILE_FLAG_DELETE_ON_CLOSE:文件被关闭后立即被系统自动删除
FILE_FLAG_RANDOM_ACCESS:对文件进行随机读写操作

hTemplateFile:指定了一个文件模板的句柄,该文件模板的所有属性都会被复制到当前创新的文件中.win95不支持本参数,建议在参数中使用NULL.当打开或创建文件成功的时候函数返回一个文件句柄,失败返回INVALID_HANDLE_VALUE,这个值是-1而不是NULL

关闭文件用

invoke CloseHandle,hFile

2移动文件指针
调整文件指针使用SetFilePointer函数

invoke SetFilePointer,hFile,lDistanceToMove,lpDistanceToMoveHigh,dwMoveMethod

hFile:是CreateFile返回的文件句柄
lDistanceToMove:指定要移动的距离.
ldistanceToMoveHigh:是一个指针指向一个32位变量存放移动距离的高32位,他与lDistanceToMove组成一个64位地址,但在X86平台上的windows版本中,文件长度不会超过4G,所以一般设置为NULL
dwMoveMethod指定了移动模式,有3个值
FILE_GEGIN:总是从文件头部开始移动
FILE_CURRENT:从当前的文件指针处开始移动
FILE_END:从文件尾开始移动
当lDistanceToMoveHigh=NULL时,如果函数执行失败返回值是-1,否则返回新的文件指针

可以使用以下代码获得当前指针的位置

invoke SetFilePointer,hFile,0,NULL,FILE_CURRENT

SetEndOfFile设置文件长度

invoke SetEndOfFile,hFile

3读写文件
读写文件可以使用ReadFile/WriteFile,这两个函数读写方式可以是同步或异步
也可以用ReadFileEx/WriteFileEx,这两个函数只用于异步读写

ReadFile用法

invoke ReadFile,hFile,lpBuffer,nNumberOfBytesToRead,lpNumberOfBytesRead,lpOverlapped

hFile是文件句柄
lpBuffer指向一个缓冲区,函数会将读出的数据传送到这里
nNumberOfBytesToRead指定需要读入的字节数
lpNumberOfBytesRead指向一个dword变量,函数将在这里返回实际读入的字节数
lpOverlapped参数指向一个OVERLAPPED结构,供函数在异步读取文件时使用,同步读写中为NULL
读取文件失败,则返回0,成功则函数返回非0值
例:

invoke ReadFile,@hFile,addr @szReadBuffer,sizeof @szReadBuffer,addr @dwBytesRead,0

读出的字节数保存在@dwBytesRead中.

WriteFile用法

invoke WriteFile,hFile,lpBuffer,nNumberOfBytesToWrite,lpNumberOfBytesWriten,lpOverlapped

hFile:文件句柄
lpBuffer:指向一个缓冲区,当中包含有要写入的文件数据
nNumberOfBytesToWrite:指定要写入的字节数
lpNumberOfBytesWriten:函数在这里返回成功写入的字节数
lpOverlapped:异步结构,同步时为NULL
写入文件时可能会由于多种原因使数据丢失
可以使用FlushFileBuffers函数来清空数据缓冲区

invoke FlushFileBuffers,hFile

总之如果这个函数执行成功的话,就能够保证所有的数据以经被传送.如果成执行成功返回值是非0值,失败返回0

4文件的共享
加锁可以防止其他进程对该区域进行读取或写入操作,加锁与解锁使用LockFile与UnlockFile也可以使用LockFileEx与UnlockFileEx,这两个函数使用异步方式执行.

invoke LockFile,hFile,dwFileOffsetLow,dwFileOffsetHigh,nNumberOfBytesToLockLow,nNumberOfBytesToLockHigh
invoke UnlockFile,hFile,dwFileOffsetLow,dwFileOffsetHigh,nNumberOfBytesToLockLow,nNumberOfBytesToLockHigh

dwFileOffsetLow和dwFileOffsetHigh参数组合起来指定了加锁区域的开始位置
dwNumberOfBytesToLockLow和dwNumberOfBytesToLockHigh组合指定加锁区域的大小,windows中,可以只使用低32位
注意:不能对一个区域重复加锁,两个不同的加锁区域也不能重叠,在对文件加锁与解锁操作的区域也必须一一对应,必须一次全部解锁,不能分次解锁.当程序读取一个可能被其它时程加锁的程序时,如果读取失败,必须调用GetLastError来获取失败原因,如果是因为锁定造成的,那可以等待一段时间后继续读取.

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注