VC的文件操作

导读:
  各种关于文件的操作在程序设计中是十分常见,如果能对其各种操作都了如指掌,就可以根据实际情况找到最佳的解决方案,从而在较短的时间内编写出高效的代码,因而熟练的掌握文件操作是十分重要的。本文将对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
  {
  if (chSectionNames[i]==0)
  if (chSectionNames[i]==chSectionNames[i+1])
  break;
  }
  iMaxCount=i+1; //要多一个0号元素。即找出全部字符串的结束部分。
  arrSection.RemoveAll();//清空原数组
  for(i=0;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
  {
  if (chKeyNames[i]==0)
  if (chKeyNames[i]==chKeyNames[i+1])
  break;
  }
  iMaxCount=i+1; //要多一个0号元素。即找出全部字符串的结束部分。
  arrKey.RemoveAll();//清空原数组
  arrValue.RemoveAll();
  for(i=0;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
  {
  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
  TRACE("%s/n",arrSection[i]);
  */
  /*枚举全部键名及值
  CStringArray arrKey,arrValue;
  n=ini.GetKeyValues(arrKey,arrValue,"段1");
  for(int i=0;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 &¤t == 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的其他函数

本文转自
http://www.xrss.cn/Dev/C/200781515684.Html
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值