const char *与char * const的区别。C语言对文件读写的支持,FILE指针;文本文件和二进制文件的区别。用文本方式读写文件和以二进制方式读写文件的注意事项。C++对文件读写的支持,ofstream和ifstream的用法。Win32 SDK对文件读写的支持,CreateFile函数、WriteFile函数、ReadFile函数的使用;MFC对文件读写的支持,CFile类和CFileDialog的使用,文件过滤器的设置。win.ini文件和注册表的读写方式及相关知识点。 1.区分指针常量和指向常量的指针 char ch[5]="lisi"; //指针常量 const char *pStr=ch; //指向常量的指针:指向内容不可改变,指针值可修改(只是指向的内容为常量) char *const pStr=ch; //表示指针本身是常量:指向内容可变,指针值不可改变 2.新建一个File的MFC工程,新建一个“文件”子菜单:写入文件 IDM_FILE_WRITE;读取文件 IDM_FILE_READ;分别增加命令响应(view类)。 FILE *fopen( const char *filename, const char *mode ); //mode参数: r只读 w打开空文件来写 a添加到文件末尾 r+既读又写 w+打开空文件读写 a+读和添加到文件尾(append) t b c n 在“写入文件”命令响应中: FILE *pOpen=fopen(("1.txt","w"); 写文件: size_t fwrite( const void *buffer, size_t size, size_t count, FILE *stream ); //指向将被写入的数据;项目大小(字节数);将被写入的最大的项目数量;指向FILE结构体的指针 fwrite("http://www.baidu.com",1,strlen("http://www.baidu.com"),pFile); (这样,按下“写入文件”时1.txt是空的,当程序退出了才有内容) 先在内存中添加到文件缓冲区,当缓冲区满了再送到磁盘区。 fclose(pFile); //关闭程序,写入到磁盘区。 但如果要再写入,就必须再打开文件。所以最好用fflush fflush(pFile); //刷新文件 文件写入的位置是由文件指针位置决定,可用fseek设置其位置。 int fseek( FILE *stream, long offset, int origin ); //FILE指针;从开始偏移的字节数;开始的位置(可设置为SEEK_CUR当前文件指针的位置,SEEK_END文件末尾,SEEK_SET文件开始)。 在fwrite后添加: fseek(pFile,0,SEEK_SET); //文件开始 fwrite("ftp:://",1,strlen("ftp:://"),pFile); 在“读取文件”中:要读取文件 size_t fread( void *buffer, size_t size, size_t count, FILE *stream ); //存储数据的 位置;项目大小的字节数;将被读的项目的最大数量;FILE指针 FILE *pFile=fopen("1.TXT","r"); char ch[100]; fread(ch,1,100,pFile); MessageBox(ch); fclose(pFile); 但这时后面会输出一大堆乱码,因为字符串后面没有跟\0。所以可在写入的时候,多写一个,即: fwrite("http://www.baidu.com",1,strlen("http://www.baidu.com")+1,pFile); 这样MessageBox就可以正常输出了,但这样就多占用了内存(最后用了一个00)。 这时可用Memset将一块buffer设置为一个特定的字符。 void *memset( void *dest, int c, size_t count ); //到目的的指针;要设置的字符;字符的数量 memset(ch,0,100); //就初始化为0了 获取文件的长度:long ftell( FILE *stream );//获取文件指针的当前位置 这里注释掉中间部分的代码: char *pBuf; fseek(pFile,0,SEEK_END); //文件指针移动到文件末尾 int len=ftell(pFile); // pBuf=new char[len+1]; fread(pBuf,1,len,pFile); pBuf[len]=0; MessageBox(pBuf); 但这时有时乱码,因为没有把文件指针放到开始处,这里用一个void rewind( FILE *stream ); //重新定位文件指针到一个文件的开始处:rewind(pFile); 注释掉这两个命令响应的代码,然后在OnFileWrite中: FILE *pFile=fopen("2.txt","w"); char ch[3]; ch[0]='a'; ch[1]=13; ch[2]='b'; fwrite(ch,1,3,pFile); fclose(pFile); //我们只写入了3个字符,但文件有4个字节 回车是13,换行是10(回车是回到行首,换行是到下行)。写入10的时候,要加入一个13(回车)。但读取3个字节可将“ab”读取出来。因为这是按文本的方式打开。 FILE *pFile=fopen("2.txt","r"); char ch[100]; fread(ch,1,3,pFile); ch[3]=0; MessageBox(ch); //正常输出a和b 我们可以b按二进制打开(默认是t以文本方式打开):如将上面打开方式改为“rb”,则消息框只输出a了。上面用二进制方式写入的时候就准确了。 二进制文件和文本文件 文件是在计算机内存中以二进制表示的数据在外部存储介质上的另一种存放形式。文件通常分为二进制文件和文本文件。 二进制文件是包含在ASCII及扩展ASCII字符中编写的数据或程序指令的文件。一般是可执行程序、图形、图像、声音等文件。 文本文件(也称ASCII文件):它的每一个字节存储的是可表示为一个字符的ASCII代码的文件。它是以“行”为基本结构的一种信息组织和存储方式的文件,可用任何文字处理程序阅读的简单文本文件。 文本方式和二进制方式 当我们按照文本方式往文件中写入数据时,一旦遇到换行字符(10),则会转化为回车-换行(13 10)。在读取文件时,一旦遇到回车-换行组合(即连续的13 10),则会转换为换行字符(10)。(vbcrlf) 当我们按照二进制方式往文件中写入数据,则将数据在内存中的存储形式原样输出到文件中。 可用itoa将数值转成字符串,如:itoa(i,ch,10); //10是表示十进制 3.C++对文件的操作,用ofstream类。(需要包含头文件fstream.h) ofstream( const char* szName, int nMode = ios::out, int nProt = filebuf::openprot ); //文件名;打开方式;保护方式 ofstream ofs("4.txt"); ofs.write("www.baidu.com",strlen("www.baidu.com")); ofs.close; 读取文件用ifstream类 ifstream( const char* szName, int nMode = ios::in, int nProt = filebuf::openprot ); ifstream ifs("4.txt"); char ch[100]; memset(ch,0,100); //初始化为0 ifs.read(ch,100); ifs.close; MessageBox(ch); 4.win32 sdk对文件的操作 打开文件用CreateFile:可打开files,pipes管道,mailslots邮槽,交流资源,磁盘设备(only NT),consoles控制台,directories(open only)目录 HANDLE CreateFile( LPCTSTR lpFileName, // pointer to name of the file DWORD dwDesiredAccess, // access (read-write) mode 访问方式GENERIC_READ/WRITE DWORD dwShareMode, // share mode 共享方式(0就不能共享) LPSECURITY_ATTRIBUTES lpSecurityAttributes, // pointer to security attributes 安全属性结构体指针 DWORD dwCreationDisposition, // how to create写入方式 DWORD dwFlagsAndAttributes, // file attributes文件属性 FILE_ATTRIBUTE_NORMAL HANDLE hTemplateFile // handle to file with attributes to // copy (标识GENERIC_READ打开的文件,否则就忽略了) ); 写入数据用WriteFile: BOOL WriteFile( HANDLE hFile, // handle to file to write to要写的文件指针 LPCVOID lpBuffer, // pointer to data to write to file要写的数据指针 DWORD nNumberOfBytesToWrite, // number of bytes to write要写的字节数 LPDWORD lpNumberOfBytesWritten, // pointer to number of bytes written实际被写入的字节数指针 LPOVERLAPPED lpOverlapped // pointer to structure for overlapped I/O (起作用的话,打开时要设置FILE_FLAG_OVERLAPPED) ); 例子: HANDLE hFile; hFile=CreateFile("5.txt",GENERIC_WRITE,0,NULL,CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL); DWORD dwWrites; WriteFile(hFile,"http://www.baidu.com",strlen("http://www.baidu.com"),&dwWrites,NULL); CloseHandle(hFile); //因为是文件句柄 读取文件,先打开: HANDLE hFile; hFile=CreateFile("5.txt",GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); 然后用ReadFile读取: BOOL ReadFile( HANDLE hFile, // handle of file to read LPVOID lpBuffer, // pointer to buffer that receives data DWORD nNumberOfBytesToRead, // number of bytes to read LPDWORD lpNumberOfBytesRead, // pointer to number of bytes read LPOVERLAPPED lpOverlapped // pointer to structure for data ); 例如: char ch[100]; DWORD dwReads; ReadFile(hFile,ch,100,&dwReads,NULL); ch[dwReads]=0; CloseHandle(hFile); MessageBox(ch); 5.MFC对文件操作的类CFile CFile( LPCTSTR lpszFileName, UINT nOpenFlags );//文件名;打开方式 写文件 CFile file("6.txt",CFile::modeCreate | CFile::modeWrite); file.Write("http://www.baidu.com",strlen("http://www.baidu.com")); file.Close(); 读文件 CFile file("6.txt",CFile::modeRead); DWORD dwFileLen; dwFileLen=file.GetLength(); char *pBuf; pBuf=new char[dwFileLen+1]; pBuf[dwFileLen]=0; file.Read(pBuf,dwFileLen); file.Close(); MessageBox(pBuf); 6.文件对话框CFileDialog(CDialog派生……) CFileDialog( BOOL bOpenFileDialog, LPCTSTR lpszDefExt = NULL, LPCTSTR lpszFileName = NULL, DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, LPCTSTR lpszFilter = NULL, CWnd* pParentWnd = NULL ); //TRUE就是打开对话框,FALSE即是另存为对话框;缺省的文件扩展名;初始化的文件名;OPENFILENAME结构体有关;应用到文件的过滤器;…… 另存为对话框: CFileDialog filedlg(FALSE); filedlg.DoModal(); 此对象的一个成员变量m_ofn存放了OPENFILENAME的指针 typedef struct tagOFN { // ofn DWORD lStructSize; HWND hwndOwner; HINSTANCE hInstance; LPCTSTR lpstrFilter; //指向过滤器字符串的buffer指针 LPTSTR lpstrCustomFilter; DWORD nMaxCustFilter; DWORD nFilterIndex; LPTSTR lpstrFile; DWORD nMaxFile; LPTSTR lpstrFileTitle; DWORD nMaxFileTitle; LPCTSTR lpstrInitialDir; LPCTSTR lpstrTitle; //默认的对话框标题 DWORD Flags; WORD nFileOffset; WORD nFileExtension; LPCTSTR lpstrDefExt; //缺省的扩展名 DWORD lCustData; LPOFNHOOKPROC lpfnHook; LPCTSTR lpTemplateName; } OPENFILENAME; 设置对话框标题: filedlg.m_ofn.lpstrTitle="我的文件保存对话框"; 设置过滤器: filedlg.m_ofn.lpstrFilter="TEXT FILE(*.txt)"; 但这样只是显示,而没有过滤的功能 需要:="TEXT FILE(*.txt)\0*.txt" 要增加其他的:="TEXT FILE(*.txt)\0*.txt\0All Files(*.*)\0*.*" filedlg.m_ofn.lpstrDefExt="txt"; //设置默认的文件扩展名(即保存的时候只输入文件名即可) 可用CFileDialog对象的GetPathName和GetFileName获取文件全路径名和文件名。 if(IDOK==filedlg.DoModal()) { CFile file(filedlg.GetFileName(),CFile::modeCreate | CFile::modeWrite); file.Write("http://www.baidu.com",strlen("http://www.baidu.com")); file.Close(); } 打开文件对话框: CFileDialog filedlg(TRUE); filedlg.m_ofn.lpstrTitle="我的文件打开对话框"; filedlg.m_ofn.lpstrFilter="TEXT FILE(*.txt)\0*.txt\0所有文件(*.*)\0*.*\0\0"; filedlg.m_ofn.lpstrDefExt="txt"; if(IDOK==filedlg.DoModal()) { CFile file(filedlg.GetFileName(),CFile::modeRead); DWORD dwFileLen; dwFileLen=file.GetLength(); char *pBuf; pBuf=new char[dwFileLen+1]; pBuf[dwFileLen]=0; file.Read(pBuf,dwFileLen); file.Close(); MessageBox(pBuf); } 7.写WIN.INI文件用WriteProfileString拷贝一个字符串到这文件中的指定section。 BOOL WriteProfileString( LPCTSTR lpAppName, // pointer to section name 小节 LPCTSTR lpKeyName, // pointer to key name 键名 LPCTSTR lpString // pointer to string to write 将写入的字符串 ); 我们在CAPP类中的InitInstance函数中的SetRegistryKey后写。 ::WriteProfileString("http://www.baidu.com","admin","adfan"); 这样一运行,则windows系统文件夹的win.ini就被更改了。 获取win.ini文件信息用GetProfileString DWORD GetProfileString( LPCTSTR lpAppName, // address of section name LPCTSTR lpKeyName, // address of key name LPCTSTR lpDefault, // address of default string 缺省字符串 LPTSTR lpReturnedString, // address of destination buffer 若key name找不到,则拷贝default此处 DWORD nSize // size of destination buffer ); CString str; ::GetProfileString("http://www.baidu.com","admin","lisi",str.GetBuffer(100),100); AfxMessageBox(str); //&&注意这里 CWinApp的成员函数: BOOL WriteProfileString( LPCTSTR lpszSection, LPCTSTR lpszEntry, LPCTSTR lpszValue ); CString GetProfileString( LPCTSTR lpszSection, LPCTSTR lpszEntry, LPCTSTR lpszDefault = NULL ); 注意:entries的值 In Windows NT, the value is stored to a registry key.注册表值 In Windows 3.x, the value is stored in the WIN.INI file. In Windows 95, the value is stored in a cached version of WIN.INI. 这时用WriteProfileString("http://www.baidu.com","admin","adfan"); 则在win.ini中没了,而在注册表中HKCU--software--Local AppWizard下的程序名下有了这个键。 我们可修改上面的SetRegistryKey(_T("www.baidu.com")); //则在注册表中HKCU-Software-www.…… CString str; str=GetProfileString("http://www.baidu.com","admin",NULL); //读取键值 AfxMessageBox(str); 8.对注册表的操作 增加两个菜单项:IDM_REG_WRITE 写注册表 IDM_REG_READ 读注册表,分别增加命令响应 用RegCreateKey创建指定的注册表项(若已经存在就打开它) LONG RegCreateKey( HKEY hKey, // handle to an open key指向当前打开的key或者HKEY_CLASSES_ROOT等 LPCTSTR lpSubKey, // address of name of subkey to open 要打开的表项的名 PHKEY phkResult // address of buffer for opened handle ); HKEY hkey; RegCreateKey(HKEY_LOCAL_MACHINE,"Software\\http://www.baidu.com\\admin",&hkey); 用RegSetValue设置值的数据。(值包括名称 类型 数据) LONG RegSetValue( HKEY hKey, // handle to key to set value for打开的句柄或HKEY……那些 LPCTSTR lpSubKey, // address of subkey name DWORD dwType, // type of value //REG_SZ字符串类型 LPCTSTR lpData, // address of value data DWORD cbData // size of value data不包括结尾空指针 ); RegSetValue(hkey,NULL,REG_SZ,"adfan",strlen("adfan")); RegCloseKey(hkey); //关闭打开的注册表 用RegQueryValue读取指定注册表项的数据。 LONG RegQueryValue( HKEY hKey, // handle to key to query LPCTSTR lpSubKey, // name of subkey to query LPTSTR lpValue, // buffer for returned string PLONG lpcbValue // receives size of returned string 包括终止符 ); LONG lValue; RegQueryValue(HKEY_LOCAL_MACHINE,"Software\\http://www.baidu.com\\admin",NULL,&lValue); //获大小 char *pBuf=new char[lValue]; //动态分配内存 RegQueryValue(HKEY_LOCAL_MACHINE,"Software\\http://www.baidu.com\\admin",pBuf,&lValue); MessageBox(pBuf); 若要写入整型,则要调用RegSetValueEx LONG RegSetValueEx( HKEY hKey, // handle to key to set value for LPCTSTR lpValueName, // name of the value to set要设置的名字(NULL就是默认或未命名) DWORD Reserved, // reserved DWORD dwType, // flag for value type类型:ERG_DWORD等 CONST BYTE *lpData, // address of value data要设置的数据 DWORD cbData // size of value data ); DWORD dwAge=30; RegSetValueEx(hkey,"age",NULL,REG_DWORD,(CONST BYTE*)&dwAge,4); //4是字节数 用RegOpenKey打开指定注册表项 LONG RegOpenKey( HKEY hKey, // handle to open key LPCTSTR lpSubKey, // address of name of subkey to open PHKEY phkResult // address of handle to open key ); 用RegQueryValueEx可读取数值 LONG RegQueryValueEx( HKEY hKey, // handle to key to query LPTSTR lpValueName, // address of name of value to query LPDWORD lpReserved, // reserved LPDWORD lpType, // address of buffer for value type LPBYTE lpData, // address of data buffer LPDWORD lpcbData // address of data buffer size ); HKEY hkey; RegOpenKey(HKEY_LOCAL_MACHINE,"Software\\http://www.baidu.com\\admin",&hkey); DWORD dwAge; DWORD dwValue; DWORD dwType; RegQueryValueEx(hkey,"age",NULL,&dwType,(LPBYTE)&dwAge,&dwValue); CString str; str.Format("age=%d",dwAge); MessageBox(str); 删除项用RegDeleteKey LONG RegDeleteKey( HKEY hKey, // handle to open key LPCTSTR lpSubKey // address of name of subkey to delete );