1. 程式人生 > >孫鑫-MFC筆記七--檔案與登錄檔

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