配置文件

计算机是如何管理自身所存放着大量的信息的呢?windows的磁盘管理程序为我们提供了一套严密而又高效的信息组织开工---硬盘上的信息是以文件的形式被管理的。 面向存储的文件技术 什么是文件?计算机中,一篇文章、一幅图画、一个程序、一首歌曲等都是以文件的形式存储在磁盘上的,每个文件都有一个文件名。计算机就是对文件按名存取的。文件名的格式如下:主文件名.扩展名 文件名由主文件名和扩展名两部分组成,中间用小圆点隔开,其中扩展名可以省略。而扩展名是用来区分文件类型的。Windows为了区分文件的类型,一些软件系统会自动给文件加上“.wps”扩展名;画图程序画的图像文件一般为“.bmp”等。 在windows中,主文件名可以由英文字符、汉字、数字以及一些符号等组成,但不能使用+<>*?/等符号。 什么是文件夹? 在计算机中存放着数以万计的文件,为了便于管理这些文件,就像我们把文件分类放到不同的抽屉中便于查阅一样,在计算机中也有像抽屉的东西,它就是文件夹。文件夹也要有一个名字,取名的原则与文件的取名类似,只是不用再区分文件夹的类型,当文件夹多了以后,还可以把某些文件夹归到一个大文件夹中去。久而久之,就构成了计算机中庞大的磁盘文件结构。 为什么要在程序中使用文件? 通常,程序中的数据在程序运行结束后,就会从内存中清除,再次运行程序时不会自动出现。在编制程序的过程中不可避免地会遇到将某些数据永久保存的问题,当关闭程序后,依然可以使用这些数据,这时就需要进行文件操作。 文件类型 Visual c++处理的文件通常分为两种: 文本文件:只可被任意文本编辑器读取ASCII文本。 二进制文件:指对包含任意格式或无格式数据的文件的统称。 这里只介绍文本文件的读写,INI文件也属于文本文件的范畴,且INI文件的结构和用途与普通的文本文件不同,所以会单独介绍。 第一部分:文本文件 文本文件的读写 认识CFile类;认识文本文件;能够正确灵活应用文本文件存取信息;避免文本文件读写的常见误区。 CFile是MFC的文件操作基本类,它直接支持无缓冲的二进制磁盘I/O操作,并通过其派生类支持文本文件、内存文件和socket文件。 客户操作记录实例功能预览及关键知识点 许多系统,出于安全或其他原因,常常要求随时对键盘进行监控,利用Hook(钩子)技术编写的应用程序能够很好地达到这个目的。本软件就制作了一个客户操作记录软件,即在软件运行过程中,用户在键盘上的按键操作会被记录下来,这样对维护软件的正常运行非常有利。 只要启动客户操作记录软件后,不管输入焦点是否在本软件上,按键都会被记录下来。我们需要的是键盘的系统监控,只要本软件在运行,无论当前计算机在做什么,都能监测到用户按键的行为并做出反应,这就要用到Hook技术。 Hook技术在很多特殊软件中广泛应用,如,金山词霸的“取词”功能,就用到了Hook计技术。 钩子的本质是一段用以处理系统消息的程序,通过系统调用,将其挂入系统。钩子的种类很多,每种钩子可以截获并处理相应的消息,每当特定的消息发出,在到达目的窗口之前,钩子程序先行截获该消息、得到对此消息的控制权。此时在钩子函数中就可以对截获的消息进行加工处理,甚至可以强制结束消息的传递。 从钩子的本质来看,可以优先截获操作系统的各种消息进行处理,所以它几乎无所不能,因为windows的应用程序都是基于消息驱动的,应用程序的操作都依赖于它所得到的消息的类型及内容。 如果Hook过程在应用程序中实现,若应用程序不是当前窗口时,该Hook就补齐作用;如果Hook在DLL中实现,程序在运行中动态调用它,它能实时对系统进行监控。根据需要,我们采用的是在DLL中实现Hook的方式。 (应用程序exe? 和DLL的区别所在) 文本文件存储原理 字符被计算机处理时都是以二进制代码的形式出现的,即一个字符对应一个8位二进制数,这种二进制码的集合就是所谓的ASCII码。 基本的ASCII码有128个,最高位都是0,对应的十进制数是0-127。键盘上的字符,如英文字母、数字和一些常用符号,使用基本ASCII部分。如数字“0”的ASCII码用二进制数表示就是00110000(即十进制数48)。 扩展的ASCII码有128个,最高位是1,对应的十进制数是128-255。一些制表符和其他符号使用扩展的ASCII码部分。 为解决汉字的存储和显示问题,我国制定了国际GB2312。据此规定,一个汉字由2个扩展的ASCII码组成,这种高位为1的双字节汉字编码就是汉字的机内码,简称为内码。例如,汉字“学”的机内码用二进制数表示就是11010001 10100111(即十进制数206 和167 ),用十进制表示就是53671(206*256+167)。对于字符,文本文件存储的是它的ASCII码,对于汉字,文本文件存储的是它的内码,即两位ASCII码,如字符串“0学0”,在文本文件中存储的内容是00110000 11010001 10100111 00110000 正确的文本文件读写过程 1.定义文件变量;2.打开指定的文件;3.向从文本文件中写入信息;4.从文本文件中读取信息;5.关闭文件 下面具体介绍如何实现这些过程。 1.定义文件变量 定义文件变量格式:CStdioFile 文件变量; 例如,定义一个名称为f1的文件变量,语句如下:CStdioFile f1; 2.打开指定文件 可以直接通过CStdioFile的构造函数来打开磁盘文件,同时可以用标志位指定打开方式(只读、只写、读写等): CStdioFile(LPCTSTR lpszFileName,UINT nOpenFlags); 其中,lpszFileName表示要打开的文件名,可以是相对路径或绝对路径 nOpenFlags设置文件打开方式标志位,可以指定用“|”连接多个标志位。下面是常用的打开标志: CFile::typeText:以文本文件的形式打开文件 CFile::typeBinary:以二进制文件的形式打开文件 CFile::modeCreate:如果指定文件名的文件不存在,则新建文件;如果文件存在并且没有设置CFile::modeNoTruncate标志,则清空文件。 CFile::modeNoTruncate:如果文件存在,不把它的长度删除为0(即不清空文件中的数据)。 CFile::modeRead:以只读方式打开文件 CFile::modeReadWrite:以可读可写方式打开文件 CFile::modeWrite:以只写方式打开文件 CFile::shareDenyNone:文件打开后,不禁止其他进程对文件的读写操作 CFile::shareExclusive:文件打开后,禁止其他进程对文件的读写操作 CFile::shareDenyRead:文件打开后,禁止其他进程对文件的读操作 CFile::shareDenyWrite:文件打开后,禁止其他进程对文件的写操作 此外,可以不在构造函数中打开文件,而仅仅调用空的构造函数CStidoFile(),然后用CStdioFile::Open()打开文件。Open函数的前两个参数和非空构造函数的参数相同,其声明如下: BOOL Open(LPCTSTR lpszFileName,UINT nOpenFlags,CFileException* pError=NULL); 第3个参数与打开失败时的异常处理有关。 实例1:以只读方式打开一个文件 步骤: 使用AppWizard创建一个对话框应用程序,删除其自动产生的所有控件,添加一个Button控件。双击控件,在相应的函数里添加代码: char * pszFileName="C://myfile.txt"; CStdioFile myFile; CFileException fileException; if(!myFile.Open(pszFileName,CFile::modeCreate|CFile::typeText|CFile::modeRead),&fileException) { TRACE("Can't open file %s, error = %u/n",pszFileName,fileException.m_cause); } 运行结果:如果C:/下没有myfile.txt文件,则新生成该文件。 3.向从文本文件中写入信息 CStdioFile提供了函数WriteString来向文本文件中写入文本,WriteString函数的格式如下: void WriteString(LPCTSTR lpsz); WriteString的参数lpsz是一个以”/0”字符结束的字符串,要把这个字符串的内容写入文件。 提示:使用WriteString函数时,如果希望每执行一次WriteString,文本文件中的内容就会自动换行一次,那么就需要在需要换行的地方输出“/n”: myFile.WriteString(“第1行/n”); 实例2:向文件中写入文本 建立MFC基于对话框的程序,删除自动添加的所有控件,添加一个“确定”按钮,双击按钮,按默认添加事件函数,双击按钮,在相应的函数处添加如下代码: char* pszFileName="C://myfile.txt"; CStdioFile myFile; CFileException fileException; if(myFile.Open(pszFileName,CFile::typeText|CFile::modeCreate|CFile::modeReadWrite),&fileException) { myFile.WriteString("第1行/n"); CString strOrder; strOrder.Format("%d,%.3f",66,88.88); myFile.WriteString(strOrder); } else { TRACE("Can't open file %s,error=%u/n",pszFileName,fileException.m_cause); } 程序运行结果:C:/myfile.txt文件中内容如下: 第1行 66,88.880 4.从文本文件中读取信息 CStidoFile提供了函数ReadString来读取文本,ReadString有两种形式,一种为: virtual LPTSTR ReadString(LPTSTR lpsz, UINIT nMax); ReadString函数的参数如下: lpsz :是用户提供的一个指向字符串的指针,它用来接受从文件读出的文本,以”/0”结束。 nMax是本次所允许读入的文本字符个数,不计“/0”字符,也就是说最多能读入nMax-1个文本字符。 ReadString的返回值是一个LPTSTR类型的指针,它指向从文件读出的文本字符串,如果到达文件尾,则返回NULL。 ReadString的另一种形式为: BOOL ReadString(CString& rString); 参数rString用来容纳从文件读出的文本。 CString版本忽略回车换行符,返回值是一个布尔值。如果返回值为FALSE,表示因到达文件尾而没有读到任何字符。 提示:每执行一次ReadString,就会自动从文本文件中读取一行数据,同时文件操作指针会自动跳转到下一行。 实例3:从文件中读取文本信息 步骤:创建基于对话框的MFC程序,删除所有自动添加的控件,添加按钮控件,为按钮添加事件,并在相应的函数处,添加如下代码: char* pszFileName="C://myfile.txt"; CStdioFile myFile; CFileException fileException; if(myFile.Open(pszFileName,CFile::typeText|CFile::modeReadWrite),&fileException) { myFile.SeekToBegin(); CString str1; myFile.ReadString(str1); CString str2; myFile.ReadString(str2); AfxMessageBox(str1+str2); } else { TRACE("Can't open file %s,error=%u/n",pszFileName,fileException.m_cause); } myFile.Close(); 程序运行结果:为程序F9设置断点,然后F5单步执行,结果如下: 5.关闭文件 对文件的操作完成后,使用CloseFile关闭文件。 函数CStdioFile::Close关闭一个文件,一般一个文件使用完毕就应该关闭它: myFile.Close(); 错误的文本文件读写过程 在读写文本文件的时候,最常见的错误是---操作文件不存在。这种错误产生的典型原因有: 1.路径错误 char * pszFileName="C://Windows//MyFile.txt"; CStdioFile myFile; CFileException fileException; if(!myFile.Open(pszFileName,CFile::modeCreate|CFile::typeText|CFile::modeReadWrite),&fileException) { //文件操作代码 } else { TRACE("Can't open file %s, error = %u/n",pszFileName,fileException.m_cause); } myFile.Close(); 由于将文件变量与一个绝对路径的文件名关联,而程序的数据通常存储在相对路径下,所以一旦相对路径和相对路径不一致时,就会出错。 举例而言,上一段程序本意是想从windows的安装目录下面的MyTextFile.txt文件中读取一行数据,但是如果操作系统安装的路径不是C:/Windwos,而是C:/Winnt,那么这段程序就会出错。 解决方法是在程序中使用相对路径,改正后的程序如下: //获取windows路径 LPTSTR lpBuffer=new char[MAX_PATH]; ::GetWindowsDirectory(lpBuffer,MAX_PATH); strcat(lpBuffer,"//MyFile.txt"); CStdioFile myFile; CFileException fileException; if(myFile.Open(lpBuffer,CFile::typeText|CFile::modeCreate|CFile::modeReadWrite),&fileException) { //文件操作代码 } else { TRACE("Can't open file %s, error = %u/n",pszFileName,fileException.m_cause); } CString strFileTitle="MyFile.txt"; CStdioFile myFile; CFileException fileException; if(myFile.Open(strFileTitle,CFile::typeText|CFile::modeReadWrite),&fileException) { //文件操作代码 myFile.WriteString("测试!"); } else { TRACE("Can't open file %s, error = %u/n",pszFileName,fileException.m_cause); } myFile.Close(); 2.操作文件不存在 如果应用程序所有路径下面不存在MyFile.txt文件,那么在WriteString写入信息时就会出错。 解决办法就是在程序中打开文件前要检查是否存在此文件。如下程序: CString strFileTitle="MyFile.txt"; CFileFind finder; if(finder.FindFile(strFileTitle)) { CStdioFile myFile; CFileException fileException; if(myFile.Open(lpBuffer,CFile::typeText|CFile::modeCreate|CFile::modeReadWrite),&fileException) { //文件操作代码 } else { TRACE("Can't open file %s, error = %u/n",pszFileName,fileException.m_cause); } } else { TRACE("Can't find file %s/n",strFileTitle); } myFile.Close(); 3.超越文件权限进行读写操作 在打开文件的过程中,通过参数指定了文件的读写权限,如果读写的操作没有和相应的权限对应,就会出现错误。 下面的程序就是典型的忽略了文件操作权限的例子: CString strFileTitle="MyFile.txt"; CStdioFile myFile; CFileException fileException; if(myFile.Open(strFileTitle,CFile::typeText|CFile::modeCreate|CFile::NoTruncate|CFile::modeRead),&fileException) { //文件操作代码 myFile.WriteString("测试!"); } else { TRACE("Can't open file %s,error=%u/n",strFileTitle,fileException.m_cause); } myFile.Close(); 支招儿: 1.准确定位文件的路径 操作文件的过程中,经常需要将文本文件放在程序自身的目录中,但是如果仅仅在程序中使用不指定任何路径信息的相对路径,如: myFile.Open("MyFile.txt",CFile::modeCreate|CFile::typeText|CFile::modeReadWrite); 那么就有可能出现不能正确定位的情况,准确定位文件位置的方法是获得可执行程序自身的绝对路径,如: TCHAR FilePath[MAX_PATH]; GetModuleFileName(NULL,FilePath,MAX_PATH); (_tcstchr(FilePath,'//'))[1]=0; lstrcat(FilePath,_T("MyFile.txt")); CStdioFile myFile; CFileException fileException; if(myFile.Open(FilePath,CFile::modeCreate|CFile::typeText|CFile::modeReadWrite),&fileException) { //文件操作代码 } else { TRACE("Can't open file %s,error=%u/n",FilePath,fileException.m_cause); } myFile.Close(); 2.读文本文件指定的一行,并得到文本文件的总行数。 读文本文件指定的一行,并得到文本文件的总行数 要统计文本文件的总行数,可以从头逐行读,直到文件尾,程序: CStdioFile myFile; CFileException fileException; if(myFile.Open("MyFile.txt",CFile::modeCreate|CFile::modeNoTruncate|CFile::typeText|CFile::modeReadWrite),&fileException) { CString strContent; int order=1; while(myFile.ReadString(strContent)) { if(2==order) { AfxMessageBox(strContent); } order=order+1; } } else { TRACE("Can't open file"); } myFile.Close(); 实例演示文件操作过程 客户操作记录实例 本软件分为两个部分,一部分是DLL模块,里面利用Hook技术完成键盘监控和写入文件的功能;另一部分是界面部分,调用DLL启动和停止客户操作记录功能。 第1步:创建MFC DLL项目 第2步:创建TestHook.h文件 第3步:加入全局共享数据变量 第4步:保存DLL实例句柄 第5步:类CKeyboradHook的成员函数 第6步:创建钩子可执行程序 第1步:创建MFC DLL项目 创建一个名为HookTest的project,project的类型为选择MFC AppWizard(DLL),DLL类型为MFC Extension DLL(using shared MFC DLL) 注意:选择File->New菜单项,在弹出对话框的左边的列表框中选择MFC AppWizard(DLL). 在project name文本框中输入项目名称,HookTest;location中输入项目的存盘路径;选中Create new workspace;在platForms列表中选择Win32选项。 单击OK按钮继续下一步,在弹出的对话框中设置DLL类型为MFC Extension DLL(using shared MFC DLL). 在IDE中,选择FileView选项卡,在其中就会发现其中有HookTest.cpp文件,却没有HookTest.h文件,这是因为visual C++6.0中没有现成的钩子类,所以要自己动手创建TestHook.h文件,在其中建立钩子类。 第2步:创建TestHook.h文件 选择File菜单,再选择New菜单项,将弹出New对话框。选择files选项卡,并且选择其中的C/C++ Header File. 选中add to project,并且在对应的下拉列表中选择项目名称HookTest;在location文本框中输入项目的存盘路径,或单击右边的按钮选择相应的路径;在file对应的文本框中输入文件名HookTest.h;单击OK按钮,在IDE中自动打开Hooktest.h文件供编辑代码用; TestHook.h文件: #if _MSC_VER>1000 #pragma once #endif //_MSC_VER>1000 class AFX_EXT_CLASS CHookTest:public CObject { public: CHookTest(); ~CHookTest(); BOOL StartHook();//StartHook()函数实现安装钩子 BOOL StopHook();//StopHook()函数实现卸载钩子 }; 第3步:加入全局共享数据变量 HookTest.cpp文件中添加: //存储各个键赌赢的字符 CString cskey[TOTAL_KEYS]= { "BACKSPACE", "TAB", …… "F12", }; //存储各个键对应的键值 int nkey[TOTAL_KEYS]= { 0X08, //"BACKSPACE", 0X09, //"TAB", ……. 0x7b,//"F12", }; #pragma data_seg("mydata") //安装的键盘钩子子句柄 HHOOK glhTestHook=NULL; //DLL实例句柄 HINSTANCE glhkInstance=NULL; #pragma data_seg() 第4步:保存DLL实例句柄 DllMain函数中添加如下代码: if (dwReason == DLL_PROCESS_ATTACH) { TRACE0("HOOKTEST.DLL Initializing!/n"); //扩展DLL仅初始化一次 if (!AfxInitExtensionModule(HookTestDLL, hInstance)) return 0; //DLL加入动态MFC类库中 new CDynLinkLibrary(HookTestDLL); //保存DLL实例句柄 glhkInstance=hInstance; } else if (dwReason == DLL_PROCESS_DETACH) { TRACE0("HOOKTEST.DLL Terminating!/n"); //终止这个链接库前调用它 AfxTermExtensionModule(HookTestDLL); } return 1; // ok 第5步:类CKeyboradHook的成员函数 //KeyboradProc函数 LRESULT WINAPI KeyboradProc(int nCode,WPARAM wParam,LPARAM lParam) { for(int i=0;i
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值