WIN32汇编语言教程:第10章 内存管理和文件操作 · 10.2 文件操作(4)
invoke GetDlgItem,hWnd,IDOK invoke EnableWindow,eax,ebx ;******************************************************************** .elseif ax == IDOK invoke GetDlgItem,hWnd,IDC_FILE invoke EnableWindow,eax,FALSE invoke GetDlgItem,hWnd,IDC_BROWSE invoke EnableWindow,eax,FALSE invoke GetDlgItem,hWnd,IDOK invoke EnableWindow,eax,FALSE or dwOption,F_COUNTING call _CountWord and dwOption,not (F_COUNTING or F_FILEEND) invoke GetDlgItem,hWnd,IDC_FILE invoke EnableWindow,eax,TRUE invoke GetDlgItem,hWnd,IDC_BROWSE invoke EnableWindow,eax,TRUE invoke GetDlgItem,hWnd,IDOK invoke EnableWindow,eax,TRUE .endif ;******************************************************************** ;恢复缩进格式,请读者注意 ;******************************************************************** .else mov eax,FALSE ret .endif mov eax,TRUE ret _ProcDlgMain endp ;#################################################################### start: invoke GetModuleHandle,NULL mov hInstance,eax invoke DialogBoxParam,hInstance,DLG_MAIN,NULL,\ offset _ProcDlgMain,NULL invoke ExitProcess,NULL ;#################################################################### end start
资源文件WordCount.rc如下:
#include <resource.h>
#define ICO_MAIN 1000
#define DLG_MAIN 100
#define IDC_FILE 101
#define IDC_BROWSE 102
//##################################################################
ICO_MAIN ICON "Main.ico"
//##################################################################
DLG_MAIN DIALOG 141, 208, 201, 41
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "单词统计"
FONT 9, "宋体"
{
LTEXT "文件名", -1, 7, 8, 25, 8
EDITTEXT IDC_FILE, 35, 5, 160, 12, ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP
PUSHBUTTON "浏览(&B)", IDC_BROWSE, 115, 22, 40, 14
PUSHBUTTON "统计(&S)", IDOK, 155, 22, 40, 14, WS_DISABLED | WS_TABSTOP
}
//##################################################################
程序在_CountWord子程序中读入文件数据并处理每个字节。如果字节数据是一个字母则调用_CountLetter子程序来移动到对应的结点上;如果遇到了非字母的数据,则表示到了单词的尾部,这时以参数0来调用_CountLetter子程序,这样就可以在结点上增加计数并将结点指针复位,以便下一个单词开始的时候重新从根结点开始扫描。
最后,程序调用_WalkTree子程序输出记录文件,这是一个递归调用的子程序,当程序将本节点代表的单词及计数输出后,发现还存在下层节点的话,则继续递归调用处理下一个结点。
接下来转入正题:结合例子中的代码讨论读写文件的函数。
1. 打开和关闭文件
要对文件进行操作的第一个步骤是打开文件,文件打开成功后将返回一个文件句柄,以后所有对文件的操作都要用到这个文件句柄。
打开文件使用的函数是CreateFile,读者一定认为是搞错了,这是创建文件,打开文件不是OpenFile吗?没有错!在Win32中不能使用OpenFile函数(Win16中倒是有OpenFile函数),不管是打开文件还是创建文件使用的都是CreateFile函数。CreateFile函数的参数又多又复杂,读者千万不要被下面的内容吓住了。
CreateFile函数的用法是:
invoke CreateFile,lpFileName,dwDesiredAccess,\
dwShareMode,lpSecurityAttributes,dwCreationDisposition,\
dwFlagsAndAttributes,hTemplateFile
各参数的含义如下:
lpFileName指向存放有文件名的缓冲区,文件名是一个以0结尾的字符串,字符串的最大长度为MAX_PATH(这个值在Windows.inc文件中定义为260),Win32可以用文件函数处理多种对象,所以CreateFile函数可以打开多种对象,包括:
● 控制台(Consoles)——Windows中类似于MS-DOS方式的界面窗口。
● 通信设备(Communications resources)——包括串口等设备。
● 目录(Directories)和文件(Files)。
● 邮件槽(Mailslots)——在网络环境下,在同一网段中可以用Mailslots提供的一条单向的通信路径,将信息由一个发送者传送到一个或者多个接收者中。
● 管道(Pipes)——两个进程可以通过管道交换数据,也可以用管道在网络中的服务器和工作站之间交换数据。
CreateFile以不同格式的文件名来区分操作的对象,普通的“驱动器:\路径\文件名”之类的格式指的就是普通的文件;当指定“COM1”为文件名的时候,操作的对象是第一个串口;如果文件名是“\\.\mailslot\filename”格式,那么要操作的就是邮件槽了;要打开的文件也可以是网络上其他主机中的文件,这时可以用“\\服务器名\共享目录名\文件名”方式来指定文件名。在本章中,只讨论对普通文件的操作。
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 ? ;本结构的长度
lpSecurityDescriptor DWORD ?
bInheritHandle DWORD ? ;是否允许继承
SECURITY_ATTRIBUTES ENDS
nLength字段需要设置为结构的长度,将bInheritHandle字段设置为TRUE就可以使句柄能够被子进程继承。
dwCreationDisposition参数用来设置文件已经存在或不存在时系统采取的动作,在这里指定不同的标志就可以决定函数执行的功能究竟是创建文件还是打开文件,参数可能的取值为:
● CREATE_NEW——创建新文件,如果文件已经存在函数会返回失败。
● CREATE_ALWAYS——创建新文件,如果文件已经存在则清除原文件。
● OPEN_EXISTING——打开存在的文件,当文件不存在时函数会返回失败。
● OPEN_ALWAYS——如果文件已经存在,则打开,不存在则创建新文件。
上页:第10章 内存管理和文件操作 · 10.2 文件操作(2) 下页:第10章 内存管理和文件操作 · 10.2 文件操作(5)