(孙鑫 十二) 文件操作

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
);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值