<menu id="w8yyk"><menu id="w8yyk"></menu></menu>
  • <dd id="w8yyk"><nav id="w8yyk"></nav></dd>
    <menu id="w8yyk"></menu>
    <menu id="w8yyk"><code id="w8yyk"></code></menu>
    <menu id="w8yyk"></menu>
    <xmp id="w8yyk">
    <xmp id="w8yyk"><nav id="w8yyk"></nav>
  • 網站首頁 > 物聯資訊 > 技術分享

    VC的文件操作

    2016-09-28 00:00:00 廣州睿豐德信息科技有限公司 閱讀
    睿豐德科技 專注RFID識別技術和條碼識別技術與管理軟件的集成項目。質量追溯系統、MES系統、金蝶與條碼系統對接、用友與條碼系統對接 各種關于文件的操作在程序設計中是十分常見,如果能對其各種操作都了如指掌,就可以根據實際情況找到最佳的解決方案,從而在較短的時間內編寫出高效的代碼,因而熟練的掌握文件操作是十分重要的。本文將對Visual C++中有關文件操作進行全面的介紹,并對在文件操作中經常遇到的一些疑難問題進行詳細的分析。


      1.文件的查找 
      當對一個文件操作時,如果不知道該文件是否存在,就要首先進行查找。MFC中有一個專門用來進行文件查找的類CFileFind,使用它可以方便快捷地進行文件的查找。下面這段代碼演示了這個類的最基本使用方法。 
      CString strFileTitle; 
      CFileFind finder; 
      BOOL bWorking = finder.FindFile("C:\\windows\\sysbkup\\*.cab"); 
      while(bWorking) 
      { 
      bWorking=finder.FindNextFile(); 
      strFileTitle=finder.GetFileTitle(); 
      }


      2.文件的打開/保存對話框 
      讓用戶選擇文件進行打開和存儲操作時,就要用到文件打開/保存對話框。MFC的類CFileDialog用于實現這種功能。使用CFileDialog聲明一個對象時,第一個BOOL型參數用于指定文件的打開或保存,當為TRUE時將構造一個文件打開對話框,為FALSE時構造一個文件保存對話框。 
      在構造CFileDialog對象時,如果在參數中指定了OFN_ALLOWMULTISELECT風格,則在此對話框中可以進行多選操作。此時要重點注意為此CFileDialog對象的m_ofn.lpstrFile分配一塊內存,用于存儲多選操作所返回的所有文件路徑名,如果不進行分配或分配的內存過小就會導致操作失敗。下面這段程序演示了文件打開對話框的使用方法。 
      CFileDialog mFileDlg(TRUE,NULL,NULL, 
      OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT|OFN_ALLOWMULTISELECT, 
      "All Files (*.*)|*.*||",AfxGetMainWnd()); 
      CString str(" ",10000); 
      mFileDlg.m_ofn.lpstrFile=str.GetBuffer(10000); 
      str.ReleaseBuffer(); 
      POSITION mPos=mFileDlg.GetStartPosition(); 
      CString pathName(" ",128); 
      CFileStatus status; 
      while(mPos!=NULL) 
      { 
      pathName=mFileDlg.GetNextPathName(mPos); 
      CFile::GetStatus( pathName, status ); 
      }


      3.文件的讀寫 
      文件的讀寫非常重要,下面將重點進行介紹。文件讀寫的最普通的方法是直接使用CFile進行,如文件的讀寫可以使用下面的方法: 
      //對文件進行讀操作 
      char sRead[2]; 
      CFile mFile(_T("user.txt"),CFile::modeRead); 
      if(mFile.GetLength()<2) 
      return; 
      mFile.Read(sRead,2); 
      mFile.Close(); 
      //對文件進行寫操作 
      CFile mFile(_T("user.txt "), CFile::modeWrite|CFile::modeCreate); 
      mFile.Write(sRead,2); 
      mFile.Flush(); 
      mFile.Close(); 
      雖然這種方法最為基本,但是它的使用繁瑣,而且功能非常簡單。我向你推薦的是使用CArchive,它的使用方法簡單且功能十分強大。首先還是用CFile聲明一個對象,然后用這個對象的指針做參數聲明一個CArchive對象,你就可以非常方便地存儲各種復雜的數據類型了。它的使用方法見下例。 
      //對文件進行寫操作 
      CString strTemp; 
      CFile mFile; 
      mFile.Open("d:\\dd\\try.TRY",CFile::modeCreate|CFile::modeNoTruncate|CFile::modeWrite); 
      CArchive ar(&mFile,CArchive::store); 
      ar<<  ar.Close(); 
      mFile.Close(); 
      //對文件進行讀操作 
      CFile mFile; 
      if(mFile.Open("d:\\dd\\try.TRY",CFile::modeRead)==0) 
      return; 
      CArchive ar(&mFile,CArchive::load); 
       ar>>strTemp; 
      ar.Close(); 
      mFile.Close(); 
      CArchive的 << 和>> 操作符用于簡單數據類型的讀寫,對于CObject派生類的對象的存取要使用ReadObject()和WriteObject()。使用CArchive的ReadClass()和WriteClass()還可以進行類的讀寫,如: 
      //存儲CAboutDlg類 
      ar.WriteClass(RUNTIME_CLASS(CAboutDlg)); 
      //讀取CAboutDlg類 
      CRuntimeClass* mRunClass=ar.ReadClass(); 
      //使用CAboutDlg類 
      CObject* pObject=mRunClass->CreateObject(); 
      ((CDialog* )pObject)->DoModal(); 
      雖然VC提供的文檔/視結構中的文檔也可進行這些操作,但是不容易理解、使用和管理,因此雖然很多VC入門的書上花費大量篇幅講述文檔/視結構,但我建議你最好不要使用它的文檔。關于如何進行文檔/視的分離有很多書介紹,包括非常著名的《Visual C++ 技術內幕》。 
      如果你要進行的文件操作只是簡單的讀寫整行的字符串,我建議你使用CStdioFile,用它來進行此類操作非常方便,如下例。 
      CStdioFile mFile; 
      CFileException mExcept; 
      mFile.Open( "d:\\temp\\aa.bat", CFile::modeWrite, &mExcept); 
      CString string="I am a string."; 
      mFile.WriteString(string); 
      mFile.Close();


     4.臨時文件的使用 

      正規軟件經常用到臨時文件,你經常可以會看到C:\Windows\Temp目錄下有大量的擴展名為tmp的文件,這些就是程序運行是建立的臨時文件。臨時文件的使用方法基本與常規文件一樣,只是文件名應該調用函數GetTempFileName()獲得。它的第一個參數是建立此臨時文件的路徑,第二個參數是建立臨時文件名的前綴,第四個參數用于得到建立的臨時文件名。得到此臨時文件名以后,你就可以用它來建立并操作文件了,如: 
      char szTempPath[_MAX_PATH],szTempfile[_MAX_PATH]; 
      GetTempPath(_MAX_PATH, szTempPath); 
      GetTempFileName(szTempPath,_T ("my_"),0,szTempfile); 
      CFile m_tempFile(szTempfile,CFile:: modeCreate|CFile:: modeWrite); 
      char m_char='a'; 
      m_tempFile.Write(&m_char,2); 
      m_tempFile.Close(); 
      5.文件的復制、刪除等 
      MFC中沒有提供直接進行這些操作的功能,因而要使用SDK。SDK中的文件相關函數常用的有CopyFile()、CreateDirectory()、DeleteFile()、MoveFile()。它們的用法很簡單,可參考MSDN。


    *********************************************************************************************************************
    ×××××××××××××××××××××××××××××××××××××××××××××××××
    *********************************************************************************************************************
    如何進行文件操作

    [1]顯示對話框,取得文件名

    CString FilePathName;
    CFileDialog dlg(TRUE);///TRUE為OPEN對話框,FALSE為SAVE AS對話框
    if (dlg.DoModal() == IDOK)
    FilePathName=dlg.GetPathName();

    相關信息:CFileDialog 用于取文件名的幾個成員函數:
    假如選擇的文件是C:\WINDOWS\TEST.EXE
    則(1)GetPathName();取文件名全稱,包括完整路徑。取回C:\WINDOWS\TEST.EXE
    (2)GetFileTitle();取文件全名:TEST.EXE
    (3)GetFileName();取回TEST
    (4)GetFileExt();取擴展名EXE

    [2]打開文件
    CFile file("C:\HELLO.TXT",CFile::modeRead);//只讀方式打開
    //CFile::modeRead可改為 CFile::modeWrite(只寫),
    //CFile::modeReadWrite(讀寫),CFile::modeCreate(新建)
    例子:
    {
    CFile file;
    file.Open("C:\HELLO.TXT",CFile::modeCreate|Cfile::modeWrite);
    .
    .
    .
    }

    [3]移動文件指針
    file.Seek(100,CFile::begin);///從文件頭開始往下移動100字節
    file.Seek(-50,CFile::end);///從文件末尾往上移動50字節
    file.Seek(-30,CFile::current);///從當前位置往上移動30字節
    file.SeekToBegin();///移到文件頭
    file.SeekToEnd();///移到文件尾

    [4]讀寫文件
    讀文件:
    char buffer[1000];
    file.Read(buffer,1000);
    寫文件:
    CString string("自強不息");
    file.Write(string,8);

    [5]關閉文件
    file.Close();

     

     

    在我們寫的程序當中,總有一些配置信息需要保存下來,以便完成程序的功能,最簡單的辦法就是將這些信息寫入INI文件中,程序初始化時再讀入.具體應用如下:

      一.將信息寫入.INI文件中.

      1.所用的WINAPI函數原型為:

    BOOL WritePrivateProfileString( 
    LPCTSTR lpAppName, 
    LPCTSTR lpKeyName, 
    LPCTSTR lpString, 
    LPCTSTR lpFileName 
    );

      其中各參數的意義:

       LPCTSTR lpAppName 是INI文件中的一個字段名.

       LPCTSTR lpKeyName 是lpAppName下的一個鍵名,通俗講就是變量名.

       LPCTSTR lpString 是鍵值,也就是變量的值,不過必須為LPCTSTR型或CString型的.

       LPCTSTR lpFileName 是完整的INI文件名.

      2.具體使用方法:設現有一名學生,需把他的姓名和年齡寫入 c:\stud\student.ini 文件中.

    CString strName,strTemp; 
    int nAge; 
    strName="張三"; 
    nAge=12; 
    ::WritePrivateProfileString("StudentInfo","Name",strName,"c:\\stud\\student.ini");

      此時c:\stud\student.ini文件中的內容如下:

       [StudentInfo] 
       Name=張三

      3.要將學生的年齡保存下來,只需將整型的值變為字符型即可:

    strTemp.Format("%d",nAge); 
    ::WritePrivateProfileString("StudentInfo","Age",strTemp,"c:\\stud\\student.ini");


     二.將信息從INI文件中讀入程序中的變量.

      1.所用的WINAPI函數原型為:

    DWORD GetPrivateProfileString( 
    LPCTSTR lpAppName, 
    LPCTSTR lpKeyName, 
    LPCTSTR lpDefault, 
    LPTSTR lpReturnedString, 
    DWORD nSize, 
    LPCTSTR lpFileName 
    );

      其中各參數的意義:

       前二個參數與 WritePrivateProfileString中的意義一樣.

       lpDefault : 如果INI文件中沒有前兩個參數指定的字段名或鍵名,則將此值賦給變量.

       lpReturnedString : 接收INI文件中的值的CString對象,即目的緩存器.

       nSize : 目的緩存器的大小.

       lpFileName : 是完整的INI文件名.

      2.具體使用方法:現要將上一步中寫入的學生的信息讀入程序中.

    CString strStudName; 
    int nStudAge; 
    GetPrivateProfileString("StudentInfo","Name","默認姓名",strStudName.GetBuffer(MAX_PATH),MAX_PATH,"c:\\stud\\student.ini");

      執行后 strStudName 的值為:"張三",若前兩個參數有誤,其值為:"默認姓名".

      3.讀入整型值要用另一個WINAPI函數:

    UINT GetPrivateProfileInt( 
    LPCTSTR lpAppName, 
    LPCTSTR lpKeyName, 
    INT nDefault, 
    LPCTSTR lpFileName 
    );

      這里的參數意義與上相同.使用方法如下:

    nStudAge=GetPrivateProfileInt("StudentInfo","Age",10,"c:\\stud\\student.ini");


    三.循環寫入多個值,設現有一程序,要將最近使用的幾個文件名保存下來,具體程序如下:

      1.寫入:

    CString strTemp,strTempA; 
    int i; 
    int nCount=6; 
    file://共有6個文件名需要保存 
    for(i=0;i {strTemp.Format("%d",i); 
    strTempA=文件名; 
    file://文件名可以從數組,列表框等處取得. 
    ::WritePrivateProfileString("UseFileName","FileName"+strTemp,strTempA, 
    "c:\\usefile\\usefile.ini"); 
    } 
    strTemp.Format("%d",nCount); 
    ::WritePrivateProfileString("FileCount","Count",strTemp,"c:\\usefile\\usefile.ini"); 
    file://將文件總數寫入,以便讀出.

      2.讀出:

    nCount=::GetPrivateProfileInt("FileCount","Count",0,"c:\\usefile\\usefile.ini"); 
    for(i=0;i {strTemp.Format("%d",i); 
    strTemp="FileName"+strTemp; 
    ::GetPrivateProfileString("CurrentIni",strTemp,"default.fil", strTempA.GetBuffer(MAX_PATH),MAX_PATH,"c:\\usefile\\usefile.ini");

    file://使用strTempA中的內容.

    }

      補充四點: 
       1.INI文件的路徑必須完整,文件名前面的各級目錄必須存在,否則寫入不成功,該函數返回 FALSE 值. 
       2.文件名的路徑中必須為 \\ ,因為在VC++中, \\ 才表示一個 \ . 
       3.也可將INI文件放在程序所在目錄,此時 lpFileName 參數為: ".\\student.ini".

     //---------------------------------------------------------------------------------- 
    /* 
    類名:CIni 
    版本:v2.0 
    最后更新: 
    v2.0 
    夢小孩于2004年2月14日情人節 
    加入高級操作的功能 
    v1.0 
    夢小孩于2003年某日 
    一般操作完成 

    類描述: 
    本類可以于.ini文件進行操作 
    */ 

    文件 1: 

    #pragma once 

    #include "afxTempl.h" 

    class CIni 
    { 
    private: 
    CString m_strFileName; 
    public: 
    CIni(CString strFileName):m_strFileName(strFileName) 
    { 
    } 
    public: 
    //一般性操作: 
    BOOL SetFileName(LPCTSTR lpFileName); //設置文件名 
    CString GetFileName(void); //獲得文件名 
    BOOL SetValue(LPCTSTR lpSection, LPCTSTR lpKey, LPCTSTR lpValue,bool bCreate=true); //設置鍵值,bCreate是指段名及鍵名未存在時,是否創建。 
    CString GetValue(LPCTSTR lpSection, LPCTSTR lpKey); //得到鍵值. 
    BOOL DelSection(LPCTSTR strSection); //刪除段名 
    BOOL DelKey(LPCTSTR lpSection, LPCTSTR lpKey); //刪除鍵名 


    public: 
    //高級操作: 
    int GetSections(CStringArray& arrSection); //枚舉出全部的段名 
    int GetKeyValues(CStringArray& arrKey,CStringArray& arrValue,LPCTSTR lpSection); //枚舉出一段內的全部鍵名及值 

    BOOL DelAllSections(); 

    }; 

    文件 2: 

    #include "StdAfx.h" 
    #include "ini.h" 

    #define MAX_ALLSECTIONS 2048 //全部的段名 
    #define MAX_SECTION 260 //一個段名長度 
    #define MAX_ALLKEYS 6000 //全部的鍵名 
    #define MAX_KEY 260 //一個鍵名長度 

    BOOL CIni::SetFileName(LPCTSTR lpFileName) 
    { 
    CFile file; 
    CFileStatus status; 

    if(!file.GetStatus(lpFileName,status)) 
    return TRUE; 

    m_strFileName=lpFileName; 
    return FALSE; 
    } 

    CString CIni::GetFileName(void) 
    { 
    return m_strFileName; 
    } 

    BOOL CIni::SetValue(LPCTSTR lpSection, LPCTSTR lpKey, LPCTSTR lpValue,bool bCreate) 
    { 
    TCHAR lpTemp[MAX_PATH] ={0}; 

    //以下if語句表示如果設置bCreate為false時,當沒有這個鍵名時則返回TRUE(表示出錯) 
    //!*&*none-value*&!* 這是個垃圾字符沒有特別意義,這樣亂寫是防止湊巧相同。 
    if (!bCreate) 
    { 
    GetPrivateProfileString(lpSection,lpKey,"!*&*none-value*&!*",lpTemp,MAX_PATH,m_strFileName); 
    if(strcmp(lpTemp,"!*&*none-value*&!*")==0) 
    return TRUE; 
    } 

    if(WritePrivateProfileString(lpSection,lpKey,lpValue,m_strFileName)) 
    return FALSE; 
    else 
    return GetLastError(); 
    } 

    CString CIni::GetValue(LPCTSTR lpSection, LPCTSTR lpKey) 
    { 
    DWORD dValue; 
    TCHAR lpValue[MAX_PATH] ={0}; 

    dValue=GetPrivateProfileString(lpSection,lpKey,"",lpValue,MAX_PATH,m_strFileName); 
    return lpValue; 
    } 

    BOOL CIni::DelSection(LPCTSTR lpSection) 
    { 
    if(WritePrivateProfileString(lpSection,NULL,NULL,m_strFileName)) 
    return FALSE; 
    else 
    return GetLastError(); 
    } 

    BOOL CIni::DelKey(LPCTSTR lpSection, LPCTSTR lpKey) 
    { 
    if(WritePrivateProfileString(lpSection,lpKey,NULL,m_strFileName)) 
    return FALSE; 
    else 
    return GetLastError(); 
    } 


    int CIni::GetSections(CStringArray& arrSection) 
    { 
    /* 
    本函數基礎: 
    GetPrivateProfileSectionNames - 從 ini 文件中獲得 Section 的名稱 
    如果 ini 中有兩個 Section: [sec1] 和 [sec2],則返回的是 'sec1',0,'sec2',0,0 ,當你不知道 
    ini 中有哪些 section 的時候可以用這個 api 來獲取名稱 
    */ 
    int i; 
    int iPos=0; 
    int iMaxCount; 
    TCHAR chSectionNames[MAX_ALLSECTIONS]={0}; //總的提出來的字符串 
    TCHAR chSection[MAX_SECTION]={0}; //存放一個段名。 
    GetPrivateProfileSectionNames(chSectionNames,MAX_ALLSECTIONS,m_strFileName); 

    //以下循環,截斷到兩個連續的0 
    for(i=0;i<MAX_ALLSECTIONS;i++) 
    { 
    if (chSectionNames[i]==0) 
    if (chSectionNames[i]==chSectionNames[i+1]) 
    break; 
    } 

    iMaxCount=i+1; //要多一個0號元素。即找出全部字符串的結束部分。 
    arrSection.RemoveAll();//清空原數組 

    for(i=0;i<iMaxCount;i++) 
    { 
    chSection[iPos++]=chSectionNames[i]; 
    if(chSectionNames[i]==0) 
    { 
    arrSection.Add(chSection); 
    memset(chSection,0,MAX_SECTION); 
    iPos=0; 
    } 

    } 

    return (int)arrSection.GetSize(); 
    } 

    int CIni::GetKeyValues(CStringArray& arrKey,CStringArray& arrValue, LPCTSTR lpSection) 
    { 
    /* 
    本函數基礎: 
    GetPrivateProfileSection- 從 ini 文件中獲得一個Section的全部鍵名及值名 
    如果ini中有一個段,其下有 "段1=值1" "段2=值2",則返回的是 '段1=值1',0,'段2=值2',0,0 ,當你不知道 
    獲得一個段中的所有鍵及值可以用這個。 
    */ 
    int i; 
    int iPos=0; 
    CString strKeyValue; 
    int iMaxCount; 
    TCHAR chKeyNames[MAX_ALLKEYS]={0}; //總的提出來的字符串 
    TCHAR chKey[MAX_KEY]={0}; //提出來的一個鍵名 

    GetPrivateProfileSection(lpSection,chKeyNames,MAX_ALLKEYS,m_strFileName); 

    for(i=0;i<MAX_ALLKEYS;i++) 
    { 
    if (chKeyNames[i]==0) 
    if (chKeyNames[i]==chKeyNames[i+1]) 
    break; 
    } 

    iMaxCount=i+1; //要多一個0號元素。即找出全部字符串的結束部分。 
    arrKey.RemoveAll();//清空原數組 
    arrValue.RemoveAll(); 

    for(i=0;i<iMaxCount;i++) 
    { 
    chKey[iPos++]=chKeyNames[i]; 
    if(chKeyNames[i]==0) 
    { 
    strKeyValue=chKey; 
    arrKey.Add(strKeyValue.Left(strKeyValue.Find("="))); 
    arrValue.Add(strKeyValue.Mid(strKeyValue.Find("=")+1)); 
    memset(chKey,0,MAX_KEY); 
    iPos=0; 
    } 

    } 

    return (int)arrKey.GetSize(); 
    } 

    BOOL CIni::DelAllSections() 
    { 
    int nSection; 
    CStringArray arrSection; 
    nSection=GetSections(arrSection); 
    for(int i=0;i<nSection;i++) 
    { 
    if(DelSection(arrSection[i])) 
    return GetLastError(); 
    } 
    return FALSE; 
    } 


    使用方法: 
    CIni ini("c:\\a.ini"); 
    int n; 

    /*獲得值 
    TRACE("%s",ini.GetValue("段1","鍵1")); 
    */ 

    /*添加值 
    ini.SetValue("自定義段","鍵1","值"); 
    ini.SetValue("自定義段2","鍵1","值",false); 
    */ 

    /*枚舉全部段名 
    CStringArray arrSection; 
    n=ini.GetSections(arrSection); 
    for(int i=0;i<n;i++) 
    TRACE("%s\n",arrSection[i]); 
    */ 

    /*枚舉全部鍵名及值 
    CStringArray arrKey,arrValue; 
    n=ini.GetKeyValues(arrKey,arrValue,"段1"); 
    for(int i=0;i<n;i++) 
    TRACE("鍵:%s\n值:%s\n",arrKey[i],arrValue[i]); 
    */ 

    /*刪除鍵值 
    ini.DelKey("段1","鍵1"); 
    */ 

    /*刪除段 
    ini.DelSection("段1"); 
    */ 

    /*刪除全部 
    ini.DelAllSections(); 
    */

     

    VC++中以追加方式向文本文件寫入數據

     

    在VB、Asp中向文本文件追加數據很容易,只要設定一個參數為ForAppending就行了。

    Sub OpenTextFileTest

       Const ForReading = 1, ForWriting = 2, ForAppending = 8

       Dim fso, f

       Set fso = CreateObject("Scripting.FileSystemObject")

       Set f = fso.OpenTextFile("c:\testfile.txt", ForWriting, True)

       f.Write "Hello world!"

       f.Close

    End Sub


    在c語言中,追加數據也比較簡單,好像設定a+參數就可以了。

     

    今天,我要用MFC中的CStdioFile類進行文件操作,讀寫等。

    可是,看了下好像沒有簡單的方法,

    于是在網上看到這樣的寫法:

    CStdioFile file(strFile,CFile::modeCreate|CFile::modeNoTruncate|CFile::modeWrite);

    file.WriteString(strTmp);

    file.Close;


    modeNoTruncate的意思就是不要截取的意思吧

    可是,試了下這段代碼,并沒有起作用,不知道是什么原因。

    于是,在WriteString寫字符串之前加了個把指針先定位到文件末尾的代碼,就可以了

    CString strTmp="hehe\r\n";
     
    CStdioFile file(strFile,CFile::modeCreate|CFile::modeNoTruncate|CFile::modeWrite);

    file.SeekToEnd();//先定位到文件尾部

    file.WriteString(strTmp);

    file.Close;

     

    隨著Windows 2000和XP的普及,現在的大文件越來越多,而VC6中MFC的CFile類只支持不大于4GB的文件, 原因在于CFile類中使用了32位整型來處理文件,32位數的范圍是2的32次方(4GB),超過這個范圍的文件CFile就管不了,微軟.Net中VC7的CFile類支持大于4GB的文件,而.Net還不普及,開發桌面應用VC6還是首選,所以我們可以參照VC7寫一個CFile的繼承類CFile64,使它支持大于4GB的文件: 
    class CFile64 : public CFile
    {
    public:

    // Attributes
     ULONGLONG GetPosition();


    // Overridables

     virtual ULONGLONG Seek(LONGLONG lOff, UINT nFrom);
     virtual void SetLength(ULONGLONG dwNewLen);
     ULONGLONG GetLength() ;

     virtual void LockRange(ULONGLONG dwPos, ULONGLONG dwCount);
     virtual void UnlockRange(ULONGLONG dwPos, ULONGLONG dwCount);


    };


    #include "stdafx.h"
    #include "file64.h"

    ////////////////////////////////////////////////////////////////////////////
    // CFile64 implementation


    ULONGLONG CFile64::Seek(LONGLONG lOff, UINT nFrom)
    {
     ASSERT_VALID(this);
     ASSERT((HANDLE)m_hFile != INVALID_HANDLE_VALUE);
     ASSERT(nFrom == begin || nFrom == end || nFrom == current);
     ASSERT(begin == FILE_BEGIN && end == FILE_END && current == FILE_CURRENT);

       LARGE_INTEGER liOff;

       liOff.QuadPart = lOff;
     liOff.LowPart = ::SetFilePointer((HANDLE)m_hFile, liOff.LowPart, &liOff.HighPart,
       (DWORD)nFrom);
     if (liOff.LowPart  == (DWORD)-1)
       if (::GetLastError() != NO_ERROR)
         CFileException::ThrowOsError((LONG)::GetLastError(), m_strFileName);

     return liOff.QuadPart;
    }

    ULONGLONG CFile64::GetPosition() 
    {
     ASSERT_VALID(this);
     ASSERT((HANDLE)m_hFile != INVALID_HANDLE_VALUE);

       LARGE_INTEGER liPos;
       liPos.QuadPart = 0;
     liPos.LowPart = ::SetFilePointer((HANDLE)m_hFile, liPos.LowPart, &liPos.HighPart , FILE_CURRENT);
     if (liPos.LowPart == (DWORD)-1)
       if (::GetLastError() != NO_ERROR)
         CFileException::ThrowOsError((LONG)::GetLastError(), m_strFileName);

     return liPos.QuadPart;
    }

    void CFile64::LockRange(ULONGLONG dwPos, ULONGLONG dwCount)
    {
     ASSERT_VALID(this);
     ASSERT((HANDLE)m_hFile != INVALID_HANDLE_VALUE);

       ULARGE_INTEGER liPos;
       ULARGE_INTEGER liCount;

       liPos.QuadPart = dwPos;
       liCount.QuadPart = dwCount;
     if (!::LockFile((HANDLE)m_hFile, liPos.LowPart, liPos.HighPart, liCount.LowPart, 
       liCount.HighPart))
       {
      CFileException::ThrowOsError((LONG)::GetLastError(), m_strFileName);
       }
    }

    void CFile64::UnlockRange(ULONGLONG dwPos, ULONGLONG dwCount)
    {
     ASSERT_VALID(this);
     ASSERT((HANDLE)m_hFile != INVALID_HANDLE_VALUE);

       ULARGE_INTEGER liPos;
       ULARGE_INTEGER liCount;

       liPos.QuadPart = dwPos;
       liCount.QuadPart = dwCount;
     if (!::UnlockFile((HANDLE)m_hFile, liPos.LowPart, liPos.HighPart, liCount.LowPart,
       liCount.HighPart))
       {
      CFileException::ThrowOsError((LONG)::GetLastError(), m_strFileName);
       }
    }

    void CFile64::SetLength(ULONGLONG dwNewLen)
    {
     ASSERT_VALID(this);
     ASSERT((HANDLE)m_hFile != INVALID_HANDLE_VALUE);

     Seek(dwNewLen, (UINT)begin);

     if (!::SetEndOfFile((HANDLE)m_hFile))
      CFileException::ThrowOsError((LONG)::GetLastError(), m_strFileName);
    }

    ULONGLONG CFile64::GetLength() 
    {
     ASSERT_VALID(this);

       ULARGE_INTEGER liSize;
       liSize.LowPart = ::GetFileSize((HANDLE)m_hFile, &liSize.HighPart);
       if (liSize.LowPart == (DWORD)-1)
       if (::GetLastError() != NO_ERROR)
       CFileException::ThrowOsError((LONG)::GetLastError(), m_strFileName);

     return liSize.QuadPart;
    }


    /////////////////////////////////////////////////////////////////////////////

    LONGLONG是64位整型,這樣在理論上可支持的最大文件為18000000000GB,你也可以根據自己的需要重載CFile的其他函數

    RFID管理系統集成商 RFID中間件 條碼系統中間層 物聯網軟件集成
    最近免费观看高清韩国日本大全