分享
 
 
 

VC 点滴之二 文件与注册表

王朝vc·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

文件和注册表

文件操作:二进制文件和文本文件的区别。二进制文件将数据在内存中存在的模式原封不动的搬到文件中,而文本文件是将数据的asc码搬到文件中。

首先做一个读写文件的菜单,在CxxView里响应

1.C的方式:

fwrite:

size:Item size in bytes 每次写多少个字节

count:Maximum number of items to be written ,总共写几次。

FILE *p;

p=fopen("c:\\1.txt","w");

fwrite("abc",1,4,p);

fclose(p);

由于我们打开文件后文件就被映射到内存中的缓存中,我们对文件所做的操作都是在内存中完成的,如果我们不关闭文件,则内存中对文件所做的修改就不会反映(保存)到硬盘中,除非你把当前一个应用程序关闭,这是会自动执行文件关闭的操作。

fflush可以在文件不关闭的情况下将一个流(缓冲区)当中的数据清空,这里的清空是把缓冲区的数据输出到硬盘。这样可以达到边写边输出的效果。

FILE* pFile=fopen("c:\\1.txt","w");

fwrite("猎狐网络",1,strlen("猎狐网络"),pFile);

//fclose(pFile);

fflush(pFile);

fwrite("how are you",1,strlen("猎狐网络"),pFile);

fflush(pFile);

fclose(pFile);

我们发现下一次的“h”是写在了上次的“心”后面了,这是因为,对于文件来说它有一个文件字符位置的指针,这个指针不同于文件的指针,是文件结构中这个char *_ptr;成员。当我们写完“心”字后,这个指针就在“心” 字后,所以下次写“h”的时候就是在“心”的后面写。如果想将第二句在“维”的前面输出,则要移动文件的位置指针,用fseek

FILE* pFile=fopen("c:\\1.txt","w");

fwrite("猎狐网络",1,strlen("猎狐网络"),pFile);

//fclose(pFile);

fflush(pFile);

fseek(pFile,0,SEEK_SET);

fwrite("北京",1,strlen("北京"),pFile);

fflush(pFile);

fseek(pFile,0,SEEK_END);

CString str;

str.Format("文件大小:%d",ftell(pFile));

MessageBox(str);

fclose(pFile);

读文件

FILE* pFile=fopen("c:\\1.txt","r");

char buf[100];

fread(buf,1,100,pFile);//虽然读出的数据超出了实际字符串的长度,但输出时还是找’\0’

MessageBox(buf);

fclose(pFile);

出现了乱码,是因为输出文件的时候没有及时找到’\0’.将写文件的strlen改为sizeof

文件读写函数需要读写的时候将’\0’带上,它类似于printf和strlen等函数以’\0’作为函数结束表示。

乱码的解决也可以用

FILE* pFile=fopen("c:\\1.txt","r");

char buf[100];

fseek(pFile,0,SEEK_END);

long len=ftell(pFile);

rewind(pFile);

fread(buf,1,len,pFile);

buf[len]=0;

MessageBox(buf);

fclose(pFile);

第三种方法:

FILE* pFile=fopen("c:\\1.txt","r");

char buf[100];

memset(buf,0,100);//可以用任意的字符来填充这个内存块。

ZeroMemory(buf,100);// 只能用‘\0’字符来填充这个内存块。

fread(buf,1,100,pFile);

MessageBox(buf);

fclose(pFile);

2.C++的方式:#include "fstream.h"

写:

ofstream ofs("c:\\1.txt");

ofs.write("猎狐网络",sizeof("猎狐网络"));

ofs.close();//最好自己将文件关掉,不关也行,这个filebuf对象的析构函数为你关。

读:

ifstream ifs("c:\\1.txt");

char buf[100];

ifs.read(buf,100);

MessageBox(buf);

当我们写的代码改为

ofstream ofs("c:\\1.txt");

char str[3];

str[0]='a';

str[1]=10;

str[2]='b';

ofs.write(str,sizeof(str));

ofs.seekp(0);

ofs.write("china",sizeof("china"));

发现此时默认按照文本写和读的时候,文件的大小不符。

这是因为在用文本文件方式读写的时候,碰到了asc码为10的字符,都将被转换,写文件的时候将10前面加上13写到了文件中,读文件读到13和10,将这两个字符换成一个10.注意在用ultraEdit看的时候不要转成DOS格式。

如果以二进制文件(ios::binary)进行读写的时候就没有这种问题存在。不做任何的转换。

C++的文件操作打开文件是在构造函数里完成,关闭文件是在析构函数里完成。

3. MFC的方式:

I. 写文件:

CFile f("c:\\1.txt",CFile::modeWrite|CFile::modeCreate);

f.Write("hello",5);

a.几个标志的作用:

CFile::modeCreate:没有指定的文件就产生一个新文件,有就打开该文件,并将它裁剪到0;

CFile::modeNoTruncate :打开文件时不裁剪到0;

b.写数据到文件末尾:

CFile f("c:\\1.txt",CFile::modeWrite|CFile::modeCreate|

CFile::modeNoTruncate);

f.SeekToEnd();

f.Write("hello",5);

//file.Close();如果我不关闭的话,其析构函数会为我关闭。

II. 读文件:

CFile f("c:\\1.txt",CFile::modeRead);

char buf[10];

memset(buf,0,10);

f.read(buf,5);

MessageBox(buf);

III. 文件对话框:

保存对话框:

CFileDialog fdlg(false);

//fdlg.m_ofn.lpstrTitle="猎狐制造!";

fdlg.m_ofn.lpstrDefExt="txt";

fdlg.m_ofn.lpstrFilter="文本文件 (*.txt)\0*.txt\0所有文件 (*.*)\0*.*\0\0";

if(IDOK==fdlg.DoModal())

{

//MessageBox(fdlg.GetFileName());

CFile file(fdlg.GetFileName(),CFile::modeCreate|CFile::modeWrite);

file.Write("猎狐网络",sizeof("猎狐网络"));

file.Close();

}

打开对话框:

CFileDialog fdlg(true);

//fdlg.m_ofn.lpstrTitle="猎狐制造!";

fdlg.m_ofn.lpstrFilter="文本文件 (*.txt)\0*.txt\0所有文件 (*.*)\0*.*\0\0";

if(IDOK==fdlg.DoModal())

{

CFile file(fdlg.GetFileName(),CFile::modeRead);

char buf[100];

file.Read(buf,100);

MessageBox(buf);

}

2. 文本文件和二进制文件的区别:

文件文件是一种特殊的二进制文件,当它遇到回车键10时,写入文件时会自动地在它的前面加一个13,而读出文件时遇到1310的组合时,又把它还原到10。而二进制文件就是把数据原封不动的写入文件,原封不动的再读取出来,没有文本文件的这种转换操作。

下面的代码演示了之间的这种区别:

写入文件时:

ofstream f("c:\\1.txt");

char buf[3];

buf[0]='a';

buf[1]='\n';

buf[2]='b';

f.write(buf,3);

读出文件时:

ifstream f("c:\\1.txt");

f.setmode(filebuf::binary);

char buf[5];

memset(buf,0,5);

f.read(buf,5);

CString str;

str.Format("%d,%d,%d,%d",buf[0],buf[1],buf[2],buf[3]);

MessageBox(str);

在写入文件时不指定格式,文件将按文本格式存储,此时读出文件时指定二进制格式,读出的数据如下图:

如果注释f.setmode(filebuf::binary);语句,文件将按文本文件读出,如下图:

二、 注册表的操作

1. 读写win.ini文件:

使用API的GetProfileInt和WriteProfileString来实现一个保存窗口大小的例子。

在CMainFrame的

void CMainFrame::OnDestroy()

{

CFrameWnd::OnDestroy();

// TODO: Add your message handler code here

CRect rect;

GetWindowRect(&rect);

CString str;

str.Format("%d",rect.Width());

WriteProfileString("窗口尺寸","宽度",str);

str.Format("%d",rect.Height());

WriteProfileString("窗口尺寸","高度",str);

}

在CMainFrame的

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)

{

if( !CFrameWnd::PreCreateWindow(cs) )

return FALSE;

// TODO: Modify the Window class or styles here by modifying

// the CREATESTRUCT cs

cs.cx=GetProfileInt("窗口尺寸","宽度",100);

cs.cy=GetProfileInt("窗口尺寸","高度",100);

return TRUE;

}

演示使用API的GetProfileString.对于它的第四个参数lpReturnedString需要添一个char*来返回。这里不能添CString对象来返回,这是一个特殊的地方。别的函数一般要char*的时候都可以用CString对象来代替。

这里我们用CString的GetBuffer来添这个char*。

A CString object consists of a variable-length sequence of characters.

因为一个字符串对象由一序列长度可变的字符组成。

Returns a pointer to the internal character buffer for the CString object. The returned LPTSTR is not const and thus allows direct modification of CString contents.

返回一个CString对象内部字符的缓冲区(字符数组)的指针,这个返回的指针不是一个常量的指针,因而允许直接修改指针所指向的CString对象的内容。这个指针和CString内部字符数组的地址是相等的。

If you use the pointer returned by GetBuffer to change the string contents, you must call ReleaseBuffer before using any other CString member functions.

如果你使用这个通过GetBuffer返回的指针改变了字符串的内容,你在使用CString其他成员函数之前必须调用ReleaseBuffer。

在CWinApp的InitInstance里

CString str;

::GetProfileString("窗口尺寸","高度","无值",str.GetBuffer(100),100);

AfxMessageBox(str);

下面测试CWinApp的WriteProfileString,GetProfileString。

对于WriteProfileString有段说明

· 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

在CWinApp的InitInstance里

WriteProfileString("猎狐","vc++","菜鸟");

CString str;

str=GetProfileString("猎狐","vc++","无效值");

AfxMessageBox(str);

所以这里写的话是写到了HKEY_CURRENT_USER\Software\Local AppWizard-Generated Applications\MyFile\维新里。

实现一个简单的计数器,来限制软件的使用次数:

SetRegistryKey(_T("myboleApp"));

int x=GetProfileInt("test","times",0);

if(x>=5)

return false;

WriteProfileInt("test","times",++x);

CString str;

str.Format("你还能使用%d次",5-x);

AfxMessageBox(str);

2. 读写WIN32注册表,做两个菜单进行注册表的读写操作,写的时候先打开所要操作键,也就是返回操作键的句柄用RegCreateKey(这个句柄包含主键和子键,第一个参数可以是一个已打开的句柄或者一个预定义的保留的句柄值,如果是前面这个已打开的句柄,那么可以根据这个已打开句柄和后面子键的参数,在这个已打开键的下面创建一个新的句柄),然后根据得到的这个句柄去读写。

在使用RegSetValue进行写操作的时候,写的类型必须是REG_SZ,这个类型可以理解成已’\0’结尾的字符串,如果我们想写别的数据类型,使用RegSetValueEx.

The RegSetValue function sets the data for the default or unnamed value of a specified registry key. The data must be a text string.

RegSetValue函数为默认的或没有名字的指定的注册表键设置数据,这个数据必须是字符串。

RegSetValue最后一个参数不包括’\0’

使用新函数在注册表任意位置读写:

写:

HKEY hKey;

RegCreateKey(HKEY_LOCAL_MACHINE,"software\\猎狐",&hKey);

//RegSetValue(hKey,NULL,REG_SZ,"WeiXin",6);

//RegSetValue(hKey,"课程",REG_SZ,"WeiXin",6);

DWORD i=100;//下面的参数要的是地址,所以这里要定义这个变量

RegSetValueEx(hKey,"JSP",NULL,REG_DWORD,(CONST BYTE*)&i,4);

RegCloseKey(hKey);

读:in bytes以字节为单位

读一个默认键的值:

char *buf;

long len;

RegQueryValue(HKEY_LOCAL_MACHINE,

"software\\猎狐网络\mylyhu\abc",NULL,&len);

buf=new char[len];

RegQueryValue(HKEY_LOCAL_MACHINE,

"software\\猎狐网络\mylyhu\abc",buf,&len);

MessageBox(buf);

delete [] buf;

RegQueryValue参数说明:

If lpValue is NULL, and lpcbValue is non-NULL, the function returns ERROR_SUCCESS, and stores the size of the data, in bytes, in the variable pointed to by lpcbValue. This lets an application determine the best way to allocate a buffer for the value's data.

如果lpValue是NULL,并且lpcbValue不是NULL,这个函数返回ERROR_SUCCESS,并且通过lpcbValue所代表这个变量的指针存储数据的字节单位的的大小,这是让一个应用程序按照最好的方式去为查询值的数据分配空间

读一个有名字的键的值。

HKEY hKey;

RegCreateKey(HKEY_LOCAL_MACHINE,"software\\维新",&hKey);

DWORD dwType;

DWORD data;

DWORD len=4;

RegQueryValueEx(hKey,"JSP",NULL,&dwType,(BYTE*)&data,&len);

CString str;

str.Format("%d",data);

MessageBox(str);

::RegCloseKey(hKey);

锁注册表:

HKEY hKey;

RegCreateKey(HKEY_CURRENT_USER,"software\\microsoft\\windows\\currentversion\\policies\\system",&hKey);

DWORD x=1;

RegSetValueEx(hKey,"DisableRegistryTools",0,REG_DWORD,(CONST BYTE*)&x,4);

RegCloseKey(hKey);

解注册表

HKEY hKey;

RegCreateKey(HKEY_CURRENT_USER,"software\\microsoft\\windows\\currentversion\\policies\\system",&hKey);

DWORD x=0;

RegSetValueEx(hKey,"DisableRegistryTools",0,REG_DWORD,(CONST BYTE*)&x,4);

RegCloseKey(hKey);

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有