孫鑫-MFC筆記七--檔案與登錄檔
c 語言對檔案的操作是通過 FILE 結構體來完成的
1 定義一個檔案結構體的指標,獲取檔案結構體指標並付給
如何開啟一個檔案
FILE *fopen(const char*filename,const char *mode); //檔名,訪問方式
FILE *_wfopen(const wchar_t *filename,const wchar_t *mode);
r 讀取檔案,檔案必須存在,後面加b,就是以二進位制的方式讀
w 開啟一個空的檔案,檔案存在則內容被銷燬,不存在就建立該檔案,後面加b,就是以二進位制的方式寫
a 開啟檔案,在檔案的末尾寫入資料
r+ 為了讀和寫開啟檔案,檔案必須存在
w+ 開啟一個空檔案,
a+ 為讀取和新增開啟一個檔案
如何寫入一個檔案
size_t fwrite(const void *puffor,size_t size,size_t count,FILE *strcam);
指向將要被寫入的資料 資料單位 單位數量 檔案結構體指標
FILE *pFile=fopen("1.txt","w");
fwrite("http://www.sunxin.org",1,strlen("http://www.sunxin.org"),pFile); //此時資料已經寫入記憶體,退出程式就能看到內容
//fclose(pFile); //新增關閉檔案語句,就不必等到退出程式才能在磁碟檔案中看到內容
//但是要再次操作檔案就又必須要再次開啟檔案,不方便,可以用另一個函式 fflush();
fflush(pFile); //將緩衝區中的內容寫入磁碟檔案,這樣就不必關閉檔案才能看到檔案資料了,也方便多次操作檔案
移動檔案內容指標到指定位置
int fseek(FILE *stream,long offset,int origin); //檔案結構體指標,相對起始位置的偏移量,起始位置
起始位置取值有三個:
SEEK_CUR 當前位置
SEEK_END 檔案末
SEEK_SET 檔案頭
FILE *pFile=fopen("1.txt","w");
fwrite("http://www.sunxin.org",1,strlen("http://www.sunxin.org"),pFile);
fseek(pFile,0,SEEK_SET);
fwrite("ftp:",1,strlen("ftp:"),pFile); //此處寫入的ftp:會把原來字串的開頭http給覆蓋掉
讀取檔案
size_t fread(void *buffor,size_t size,size_t count,FILE *stream);
FILE *pFile=fopen("1.txt","r");
char ch[100];
fread(ch,1,100,pFile);
MessageBox(ch); //此處顯示的除了檔案中的字串,還有ch[100]中未佔用,其他空間的亂碼
fclose(pFile);
b 用memset()把多餘的空間內容全部清零
void *memset(void *dcst,int c,size_t count); //用指定的字元填充一塊記憶體區域
記憶體 字元 要填充的數目
memset(ch,0,100);
c獲取檔案內容指標的位置
long ftell(FILE *stream); //配合fseek()把指標移到檔案末尾,就能夠得到檔案的長度了
把檔案指標放置到檔案開始處
void rewind(FILE *strcam);
FILE *pFile=fopen("1.txt","r");
char *pBuf;
fseek(pFile,0,SEEK_END); //把檔案指標移動到檔案末尾,記得顯示檔案內容時要把指標移動回到檔案頭部
int len=ftell(pFile); //獲取檔案指標的位置,相當於得到檔案的長度了
pBuf=new char[len+1]; //根據檔案長度申請記憶體空間,使讀取檔案長度獲得一定的靈活性,注意後面加一的意義
rewind(pFile); //把檔案指標移動到檔案開頭,當然你也可以用fseek()完成這個動作
fread(pBuf,1,len,pFile); //讀取檔案
pBuf[len]=0; //把檔案末尾置零,作為結束標誌
MessageBox(pBuf); //輸出
fclose(pFile);
二進位制檔案和文字檔案
文字檔案(也稱為ASCII檔案):它的每一個位元組存放的是可表示為一個字元的ASCII程式碼的檔案。因此,給你一個整數,例如:98341,將這個整數儲存到檔案中,要求在以記事本程式開啟檔案時,顯示的是98341,則程式設計時應該將該整數轉換為字串。如果直接存入整數,最終顯示的將是98341對應的ASCII字元。
當我們按照文字方式往檔案中寫入資料時,一旦遇到換行字元(ASCII為10),則會轉換為回車-換行(ASCII為13、10)。在讀取檔案時,一旦遇到回車-換行的組合(即連續的ASCII 13、10),則會轉換為換行字元(ASCII為10)。
當我們按照二進位制方式往檔案中寫入資料,則將資料在記憶體中的儲存形式原樣輸出到檔案中。
由於二進位制檔案和文字檔案操作上的差異,我們在操作檔案的時候必須保持讀寫一致性,用什麼方式寫的,就用什麼方式讀
c++ 的方式檔案操作
寫入檔案
ofstream::ofstream //操作檔案類,要包含標頭檔案 fstream.h
ofstream();
ofstream(const char* szName,int nMode=ios::out,int nProt=filebut::openprot); //檔名,開啟方式,檔案保護說明
ofstream(filedesc fd);
ofstream(filedesc fd,char *pch,int nLength);
讀取檔案
ifstream::ifstream //操作檔案類,要包含標頭檔案 fstream.h
ifstream();
ifstream(const char* szName,int nMode=ios::out,int nProt=filebut::openprot); //檔名,開啟方式,檔案保護說明
ifstream(filedesc fd);
ifstream(filedesc fd,char *pch,int nLength);
ifstream ifs("4.txt");
char ch[100];
memset(ch,0,100);
ifs.read(ch,100);
ifs.close();
MessageBox(ch);
win32 api 操作檔案
建立檔案
HANDLE CreateFile( //該函式可以建立或者開啟控制檯,通訊資源,目錄,磁碟裝置,檔案,郵槽,管道,並返回相應控制代碼
LPCTSTR lpFileName, //檔名
DWORD dwDesiredAccess, //訪問方式,讀或寫
DWORD dwShareMode, //共享方式,為零則不共享
LPSECURITY_ATTRIBUTES lpSecurityAttributes, //建立的訪問許可權,確定返回的控制代碼是否能夠被子程序繼承,用於伺服器端軟體
DWORD dwCreationDisposition, //如何建立
DWORD dwFlagsAndAttributes, //設定檔案屬性和標記
HANDLE hTemplateFile //模板檔案控制代碼,如果在此傳入檔案控制代碼,則忽略上一個引數,如果開啟一個
); //現有檔案,則該引數被忽略
寫入資料
BOOL WriteFile(
HANDLE hFile, //檔案的控制代碼
LPCVOID lpBuffer, //記憶體指標
DWORD nNumberOfBytesToWrite, //寫多少個位元組
LPDWORD lpNumberOfBytesWritten, //返回,實際寫入到檔案的位元組數,傳入一個變數接收就行了
LPOVERLAPPED lpOverlapped //告訴系統我們需要非同步訪問資料,否則用同步io訪問資料,此引數要起作用,必須
); //在建立檔案時新增FILE_FLAG_OVERLAPPED標記,否則用NULL即可
HANDLE hFile;
hFile=CreateFile("5.txt",GENERIC_WRITE,0,NULL,CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL); //注意第二個引數,建立方式為讀取
DWORD dwWrites;
WriteFile(hFile,"http://www.sunxin.org",strlen("http://www.sunxin.org"),&dwWrites,NULL);
CloseHandle(hFile); //關閉該控制代碼
讀取檔案
BOOL ReadFile(
HANDLE hFile, //檔案控制代碼
LPVOID lpBuffer, //用來接收從檔案中讀取的資料
DWORD nNumberOfBytesToRead, //讀取的位元組數
LPDWORD lpNumberOfBytesRead, //接收實際讀取的位元組數的變數,一般用取址方式作引數
LPOVERLAPPED lpOverlapped //
);
HANDLE hFile;
hFile=CreateFile("5.txt",GENERIC_READ,0,NULL,OPEN_EXISTING, //注意第二個引數,建立方式為讀取
FILE_ATTRIBUTE_NORMAL,NULL);
char ch[100];
DWORD dwReads;
ReadFile(hFile,ch,100,&dwReads,NULL);
ch[dwReads]=0; //檔案資料末尾
CloseHandle(hFile);
MessageBox(ch);
mfc 類進行檔案操作
CFile : CObject 提供了沒有快取的,二進位制輸入輸出的磁碟服務,通過派生類間接的支援文字檔案和記憶體檔案
CFile::CFile
CFile(int hFile);
CFile(LPCTSTR lpszFileName,UINT nOpenFlags); //檔名,共享和訪問的方式
讀取檔案
CFile file("6.txt",CFile::modeCreate | CFile::modeWrite);
file.Write("http://www.sunxin.org",strlen("http://www.sunxin.org"));
file.Close();
寫入檔案
CFile file("6.txt",CFile::modeRead);
char *pBuf;
DWORD dwFileLen;
dwFileLen=file.GetLength(); //獲取檔案長度
pBuf=new char[dwFileLen+1]; //根據檔案長度申請記憶體空間
pBuf[dwFileLen]=0; //末尾置零
file.Read(pBuf,dwFileLen); //讀取檔案到記憶體
file.Close(); //關閉檔案
MessageBox(pBuf);
11、增加開啟檔案對話方塊和儲存檔案對話方塊,這都可以用一個類來完成
CFileDialog : CCommonDialog : CDialog : CWnd : CCmdTarget : CObject
CFileDialog(BOOL bOpenFileDialog,LPCTSTR lpszDefExt=NULL,LPCTSTR lpszFileName=NULL,DWORD dwFlags=OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,LPCTSTR lpszFilter=NULL,CWnd*pParentWnd=NULL);
對話方塊型別 true 開啟 false 儲存為
預設副檔名
初始檔名
標誌
檔案過濾器
父視窗指標
以上資料也可以在建立物件後,通過CFileDialog的一個成員變數m_ofn來改變,m_ofn實際上是一個OPENFILENAME型別,通過改變其中的lpstrTitle、lpstrFilter、lpstrDefExt等變數,可以改變標題欄,檔案型別過濾器、預設副檔名等等
獲取使用者選擇的檔名
CFileDialog::GetPathName //獲取的字串包含了檔案的路徑和檔名
CString GetPathName()const;
CFileDialog::GetFileName //獲取的字串只有檔名
CString GetFileName()const;
讀取檔案
CFileDialog fileDlg(FALSE);
fileDlg.m_ofn.lpstrTitle="我的檔案儲存對話方塊";
fileDlg.m_ofn.lpstrFilter="Text Files(*.txt)\0*.txt\0All Files(*.*)\0*.*\0\0"; //字串末必須以兩個空結尾
fileDlg.m_ofn.lpstrDefExt="txt"; //加\0才有檔案過濾功能
if(IDOK==fileDlg.DoModal())
{
CFile file(fileDlg.GetFileName(),CFile::modeCreate | CFile::modeWrite);
file.Write("http://www.sunxin.org",strlen("http://www.sunxin.org"));
file.Close();
}
開啟檔案
CFileDialog fileDlg(TRUE);
fileDlg.m_ofn.lpstrTitle="我的檔案開啟對話方塊";
fileDlg.m_ofn.lpstrFilter="Text Files(*.txt)\0*.txt\0All Files(*.*)\0*.*\0\0";
if(IDOK==fileDlg.DoModal())
{
CFile file(fileDlg.GetFileName(),CFile::modeRead);
char *pBuf;
DWORD dwFileLen;
dwFileLen=file.GetLength();
pBuf=new char[dwFileLen+1];
pBuf[dwFileLen]=0;
file.Read(pBuf,dwFileLen);
file.Close();
MessageBox(pBuf);
}
win.ini檔案訪問
修改win.ini檔案的函式,這個函式是為了相容16位系統而保留的,在32位系統中用登錄檔來儲存資訊
BOOL WriteProfileString(
LPCTSTR lpAppName, //段名
LPCTSTR lpKeyName, //鍵名
LPCTSTR lpString //值
);
讀取win.ini檔案的函式
DWORD GetProfileString(
LPCTSTR lpAppName, //段名
LPCTSTR lpKeyName, //鍵名
LPCTSTR lpDefault, //預設的字串,如果鍵名在檔案中找不到,該值被銬到下面一個引數中
LPTSTR lpReturnedString, //注意此處,需要的是一個記憶體指標,如果用CString接收,則可以用GetBuffer()獲取LPTSTR
DWORD nSize //記憶體大小
);
CString::GetBuffer
LPTSTR GetBuffer(int nMinBufLength);
可以通過該函式獲取的指標修改記憶體中字串的內容,但必須用ReleaseBuffer()釋放指標,如果不修改,則不用釋放
在CWinApp當中也有WriteProfileString()這個函式
CWinApp::WriteProfileString
BOOL WriteProfileString(LPCTSTR lpszSection,LPCTSTR lpszEntry,LPCTSTR lpszValue); //段名,鍵名,值
在winnt系統中,該函式修改的不是win.int檔案,而是登錄檔
HKEY_CURRENT_USER\Software\Local AppWizard-Generated Applications\File\ 中
為什麼是在Local AppWizard-Generated Applications中呢,因為在InitInstance()中有一個SetRegistryKey()設定了
SetRegistryKey(_T("Local AppWizard-Generated Applications"));
讀取登錄檔中相應的資訊
CWinApp::GetProfileString
CString GetProfileString(LPCTSTR lpszSection,LPCTSTR lpszEntry,LPCTSTR lpszDefault=NULL); //段名,鍵名,預設,返回相應值
12、登錄檔操作
開啟登錄檔項
LONG RegCreateKey(HKEY hKey, LPCTSTR lpSubKey, PHKEY phkResult); //主鍵,子健,用於接收所建立或開啟的表項控制代碼的變數
如果已有表項則開啟,沒有則建立
寫入鍵值,字串型別的
LONG RegSetValue((HKEY hKey, LPCTSTR lpSubKey,DWORD dwType,LPCTSTR lpData,DWORD cbData);//2 NULL,設定預設或沒有的資料
主鍵 子健 型別 值 值大小,位元組為單位
HKEY hKey;
RegCreateKey(HKEY_LOCAL_MACHINE,"Software\\http://www.sunxin.org\\admin",&hKey); //admin是小目錄
RegSetValue(hKey,NULL,REG_SZ,"zhangsan",strlen("zhangsan")); //zhangsan寫入到了名稱為“預設”的值名中
RegCloseKey(hKey);//關閉控制代碼
讀取資料,字串型別的
LONG RegQueryValue(HKEY hKey, LPCTSTR lpSubKey,LPTSTR lpValue,PLONG lpcbValue);
LONG lValue;
RegQueryValue(HKEY_LOCAL_MACHINE,"Software\\http://www.sunxin.org\\admin",NULL,&lValue); //第一次,得到值的大小
char *pBuf=new char[lValue]; //lValue長度包含了空結束符長度,所以此處不必加一了
RegQueryValue(HKEY_LOCAL_MACHINE,"Software\\http://www.sunxin.org\\admin",pBuf,&lValue); //第二次,將值寫入記憶體pBuf
MessageBox(pBuf);
寫入資料,數字型別
LONG RegSetValueEx(
HKEY hKey,
LPCTSTR lpValueName, //
DWORD Reserved, //保留引數,設為 0 即可
DWORD dwType, //型別
CONST BYTE *lpData,
DWORD cbData //資料大小
);
HKEY hKey;
DWORD dwAge=30;
RegCreateKey(HKEY_LOCAL_MACHINE,"Software\\http://www.sunxin.org\\admin",&hKey);
RegSetValue(hKey,NULL,REG_SZ,"zhangsan",strlen("zhangsan"));
RegSetValueEx(hKey,"age",0,REG_DWORD,(CONST BYTE*)&dwAge,4);
RegCloseKey(hKey);
讀取資料,數字型別
LONG RegOpenKey(HKEY hKey, LPCTSTR lpSubKey,PHKEY phkResult);
LONG RegQueryValueEx(
HKEY hKey,
LPCTSTR lpValueName,
LPDWORD lpReserved,
LPDWORD lpType, //接受資料型別的變數,要自己定義一個變數
LPBYTE lpdata,
LPDWORD lpcbdata
);
HKEY hKey;
RegOpenKey(HKEY_LOCAL_MACHINE,"Software\\http://www.sunxin.org\\admin",&hKey);
DWORD dwType;
DWORD dwValue;
DWORD dwAge;
RegQueryValueEx(hKey,"age",0,&dwType,(LPBYTE)&dwAge,&dwValue);
CString str;
str.Format("age=%d",dwAge);
MessageBox(str);
刪除表項
LONG RegDeleteKey(HKEY hKey, LPCTSTR lpSubKey);