【轉】第十二章 檔案操作

clearver發表於2010-03-04
閱讀本文前,我們假設您已經:
         1,知道如何建立一個單文件的App Wizard
         2,知道C++ 類、函式過載等簡單知識
         3,知道如何給View類或者Doc文件新增成員變數
         4,會用MFC的IDE除錯工具最好,那麼本文的程式您可以copy去除錯 
         5,知道如何為某個框架類新增虛擬函式或訊息處理函式
  

1, 指向常量的指標&&指標常量

Char ch[5]=”lisi”;
Const char * pStr=ch;    const char *
等同char const *
Char * const *pStr=ch;
指標是常量,指標不可更改,其內容可更改

2, 讀寫

檔案讀取操作
 FILE *pFile=fopen("1.txt","r");

 char ch[100]="0";   //陣列被賦值為全零
memset(ch,0,100);//
等同於上一句?

 //char ch[100];    //如果不把陣列賦零,也可以在寫入檔案中多寫一個空字元
 
fwrite("I Love You",1,strlen("I Love You")+1,pFile);
 //memset(ch,0,100);  
把陣列賦為全零的另一種方法。
 fread(ch,1,100,pFile);
 fflush(pFile);

3, 獲取檔案大小

fseek(pFile,0,SEEK_END);  //把檔案指標移到檔案末尾
 int n=ftell(pFile);    //
得到檔案長度

rewind(pFile);     //把指標移回檔案頭  fseek(pFile,0,SEEK_BEGIN)
 pbuf=new char[n+1];

 pbuf[n]=0;      //
檔案尾加/0作為檔案結束符
 fread(pbuf,1,n,pFile);

4, 文字和二進位制方式。讀取和寫入的保持一致
文字
:寫入, 換行(10è回車--換行(ASCII1310
      
讀取, 回車--換行(ASCII 1310è換行(10

二進位制:將資料在記憶體中的儲存形式原樣輸出到檔案中
不管是文字檔案還是二進位制檔案,都可以用文字方式或者二進位制方式中的任意一種開啟

5, 字元和數字

FILE *pFile=fopen("2.txt","w");

int i=98341;     //非要使他可用,可增加itoa(i,ch,10);
fwrite(&i,4,1,pFile); 

6, C++中檔案操作

需要加標頭檔案#include "fstream.h"
 ofstream os("3.txt");
 os.write("I love you!",strlen("I love you!"));
 os.close();  

讀檔案:

 ifstream ifs("3.txt"ios::in);
 char ch[100]="0";
memset(ch,0,100)
 ifs.read(ch,100);
 ifs.close();

//迴圈讀取檔案每一行

While(!ifs.getline(ch,100).eof())

{//do something with data in buffer ch

}

下一次重新getline之前,需要 ifs.clear()清除eof標誌

 

7, Win32API函式存取檔案

(1)寫入
HANDLE hfile;
 hfile=CreateFile("6.txt",GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
 DWORD dwWrites;
 WriteFile(hfile,"I Love You!(5)",strlen("I Love You!(5)"),&dwWrites,NULL);
 CloseHandle(hfile);
(2)
讀取
 HANDLE hfile;
 hfile=CreateFile("6.txt",GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
 char ch[100]="0";  //
如果只寫char ch[dwRead-1];可以在之後用ch[dwRead]=0設結束符
 DWORD dwRead;
 ReadFile(hfile,ch,100,&dwRead,NULL);
ch[dwRead]=0;
 CloseHandle(hfile);

8, SDK方法

1)寫入:

CFile file("7.txt",CFile::modeCreate | CFile::modeWrite);
 file.Write("I Love You 1000",strlen("I Love You 1000"));
 file.Close();

2)讀取:

CFile file("7.txt",CFile::modeRead);
 char *pBuf;
 DWORD i=file.GetLength();

pBuf=new char[i+1];
 file.Read(pBuf,i);

pBuf[i]=0;

 file.Close();

9, 構造檔案對話方塊,存取檔案方法

1)寫入:

CFileDialog fileDlg(FALSE);
 fileDlg.m_ofn.lpstrTitle="
我的檔案儲存對話方塊";
 fileDlg.m_ofn.lpstrFilter="Text Files(*.txt)/0*.txt/0All Files(*.*)/0*.*/0/0";
//
注意lpstrFilter的構造:每個段落後邊都要加/0,末尾要加兩個/0,括號裡的只是顯示,實//現在緊跟著的/0後邊,此過濾器只為過濾可見檔案使用,並不能按所見格式儲存。
 fileDlg.m_ofn.lpstrDefExt="txt";
 if(IDOK==fileDlg.DoModal())
 {
     CFile file(fileDlg.GetFileName(),CFile::modeCreate | CFile::modeWrite);
     file.Write("I Love You 1000",strlen("I Love You 1000"));
     file.Close();
 }

2)讀取

 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 i=file.GetLength();
     pbuf=new char[i+1];   //
動態建立緩衝區,值得學習
     pbuf[i]=0;
     file.Read(pbuf,i);
      MessageBox(pbuf);
     file.Close();

}

10,  讀寫配置檔案

CXXXApp::InitInstance(){

// 寫在SetRegistryKey(_T("Local AppWizard-Generated Applications"));之後(也可以重新設定表項)

::WriteProfileString("songpeng","sp","song");用來在C:/WINDOWS/win.ini中寫入資料。一方面為了相容十六位程式,另一方面提高程式執行速度
     //
win32中為[HKEY_CURRENT_USER]è[Software]è[Local Appwizard-Generated Applications]è[File]

     CString str;
     ::GetProfileString("songpeng","sp","peng",str.GetBuffer(100),100);

}

11,  讀寫登錄檔

      讀寫配置檔案的函式WriteProfileString()GetProfileString()win32下自動成為登錄檔的讀寫。

     SetRegistryKey(_T("Local AppWizard-Generated Applications"));用來在登錄檔的HKEY_CURRENT_USER->Software下增加主鍵Local AppWizard-Generated Applications
子鍵及值由WriteProfileString("songpeng","sp","song");增加

      1)寫入登錄檔:

      HKEY hkey;
     RegCreateKey(HKEY_LOCAL_MACHINE,"Software//MyItem//Name",&hkey);      RegSetValue(hkey,NULL,REG_SZ,"song",strlen("song"));
     RegSetValueEx(hKey,”age”,0,REG_DWORD,(CONST BYTE*)&dwAge,4);

     RegCloseKey(hkey);

     2)讀取登錄檔

     注意要先獲取欄位大小

     LONG lValue;
     RegQueryValue(HKEY_LOCAL_MACHINE,"Software//MyItem//Name",NULL,&lValue);
     char *buf=new char[lValue];    //
注意建立緩衝區方法
     RegQueryValue(HKEY_LOCAL_MACHINE,"Software// MyItem//Name",buf,&lValue);

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
);
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.
所以,我們要呼叫兩次RegQueryValue,第一次查詢鍵值長度,第二次獲得鍵值

 

HKEY hkey;
 RegOpenKey(HKEY_LOCAL_MACHINE, "Software//MyItem//Name",&hkey);
 //
開啟主鍵
 DWORD dwType;
 DWORD dwAge;
 DWORD dwValue;
 RegQueryValueEx(hkey,"age",0,&dwType,(LPBYTE)&dwAge,&dwValue);

其他函式:

     RegDeleteKey(); RegDeleteValue();
 

    歡迎以任何形式轉載本文,只要對您有用
    歡迎給我來信 webbery (at) sohu (dot) com (分別用@,.替換at,dot)

    韋伯主頁: http://mail.ustc.edu.cn/~bywang(提供此筆記系列相關源程式下載)
    韋伯Blog: http://webbery.tianyablog.com
參考書目和網站: 
    (1)孫鑫VC++視訊
    (2)1-6章主要參考: hbyufan的BLog
    (3)11-20章主要參考: songpeng的Blog