程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> MFC文件操作,mfc文件

MFC文件操作,mfc文件

編輯:C++入門知識

MFC文件操作,mfc文件


文件操作:二進制文件和文本文件的區別。二進制文件將數據在內存中存在的模式原封不動的搬到文件中,而文本文件是將數據的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,而讀出文件時遇到13 10 的組合時,又把它還原到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);

推擠:http://www.cnblogs.com/roucheng/p/cppyiwei.html

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved