CStdioFile类

来源:互联网 发布:数据库字段注释 编辑:程序博客网 时间:2024/04/30 19:49

参数内容:

第一个参数为路径+文件名,最后一个为错误出现的结构.

现在解释下第二个参数

CFile::modeCreate   Directs the constructor to create a new file. If the file exists already, it is truncated to 0 length.

指定构造器创建一个新的文件,如果文件已经存在,则内容截0.

CFile::modeNoTruncate   Combine this value with modeCreate. If the file being created already exists, it is not truncated to 0 length. Thus the file is guaranteed to open, either as a newly created file or as an existing file. This might be useful, for example, when opening a settings file that may or may not exist already. This option applies to CStdioFile as well.

modeNoTruncate

假如你不用这个参数的话,用modeCreate模式创建和打开一个文件,假如这个文件已经存在,则会清空这个已经存在的文件,加上modeNoTruncate的话,就不会清空这个文件了

CFile::modeRead   Opens the file for reading only.

只是以读取方式打开

CFile::modeReadWrite   Opens the file for reading and writing.

读与写同时

CFile::modeWrite   Opens the file for writing only.
只写

CFile::modeNoInherit   Prevents the file from being inherited by child processes.

阻止这个文件被子进程继承

CFile::shareDenyNone   Opens the file without denying other processes read or write access to the file.Create fails if the file has been opened in compatibility mode by any other process.

打开这个文件同时允许其它进程读写这个文件。如果文件被其它进程以incompatibility模式打开,这是create操作会失败。

CFile::shareDenyRead   Opens the file and denies other processes read access to the file. Create fails if the file has been opened in compatibility mode or for read access by any other process.

打开文件拒绝其它任何进程读这个文件。如果文件被其它进程用compatibility模式或者是读方式打开,create操作失败。

CFile::shareDenyWrite   Opens the file and denies other processes write access to the file. Create fails if the file has been opened in compatibility mode or for write access by any other process.

打开文件拒绝其它任何进程写这个文件。如果文件被其它进程用compatibility模式或者是写方式打开,create操作失败。

CFile::shareExclusive   Opens the file with exclusive mode, denying other processes both read and write access to the file. Construction fails if the file has been opened in any other mode for read or write access, even by the current process.

 以独占方式打开这个文件,不允许其它进程读写这个文件。

CFile::shareCompat   This flag is not available in 32 bit MFC. This flag maps to CFile::shareExclusivewhen used in CFile::Open.

这个标志在32位的MFC中无效。

CFile::typeText   Sets text mode with special processing for carriage return–linefeed pairs (used in derived classes only).

CFile::typeText   设置成对回车换行对有特殊处理的文本模式(仅用在派生类中) 
CFile::typeBinary   设置二进制模式(仅用在派生类中)

 

 

 

 

CStdioFile继承自CFile,一个CStdioFile 对象代表一个用运行时函数fopen 打开的C 运行时流文件。

      流式文件是被缓冲的,而且可以以文本方式(缺省)或二进制方式打开。文本方式提供对硬回车—换行符对的特殊处理。当你将一个换行符(0x0A)写入一个文本方式的CStdioFile 对象时,字节对(0x0D,0x0A)被发送给该文件。当你读一个文件时,字节对(0x0D,0x0A)被翻译为一个字节(0x0A)。 
  CStdioFile 不支持Duplicate,LockRange,和UnlockRange 这几个CFile 函数。如果在CStdioFile 中调用了这几个函数,将会出现CNoSupported 异常。 
  CStdioFile::ReadString(LPTSTR lpsz, UINT nMax); 
  读取一行文本到缓冲区,遇到“0x0D,0x0A”时停止读取,并且去掉硬回车“0x0D”,保留换行符“0x0A”,在字符串末尾添加“/0”(0x00)。nMax个字符里包含0x00这个字符。分析如下: 
  1)如果nMax <= 字符数,读取(nMax-1)个字符 + 0x00 
  2)如果nMax = 字符数 + 1,读取nMax个字符 + 0x00 
  3)如果nMax > 字符数,读取nMax个字符 + 0x0A + 0x00 
  CStdioFile::ReadString(CString &rString);(重载) 
  读取一行文本到rString,遇到回车换行符停止读取。回车和换行符不读到rString,而且末尾也没有添加“/0”。 
  CStdioFile::WriteString( LPCTSTR lpsz );(不支持CString直接写入) 
  将一个缓冲区中的数据写入与CStdioFile 对象关联的文件中。结束的空字符(“/0”)不被写入该文件。lpsz 中的所有换行符都被以一个硬回车换行符对写入该文件,即“/n”被转化成“/r/n”写入到文件里。 
  CFile的派生类CStdioFile提供了对文件进行流式的操作功能。其中函数void CStdioFile::WriteString( LPCTSTR lpsz )写入一个字符串,需要给字符串lpsz的末尾加上换行标志”/r/n”;函数bool CStdioFile::ReadString(CString &rString )从文件中读取一行,如果文件未读完返回true,否则返回false。   
    
    当CStdioFile.WriteString无法处理中文时,把工程的字符集属性 改成 使用多字节字符集 就可以了,具体设置方法如:打开项目属性-->配置属性-->常规-->字符集-->改成 使用多字节字符集
    要注意的是CStdioFile在_MSBC环境下读取任何ANSI文本数据都没问题,在UNICODE环境下读取ANSI文本中的中文时就会显示乱码。其原因是由于CStdioFile 读取ANSI文本数据时按char类型读取,在_MSBC下可以直接填充到CString,在UNICODE环境下要先将char转换成宽字符 WCHAR,然后再填充到CString,即一个汉字的两个char将变成两个UNICODE字符WCHAR。那么问题如何解决呢?实际上在UNICODE环境下,file.ReadString(strLine)取得的数据是char类型,但是存储在UNICODE字符串中。为了取得真实数据,必须对strLine进行处理。

  在CFile类中提供了2种模式,typeBinary和typeText。如果是CTextFile类的话当然要强制使用typeText类型了。那么CStdioFile是怎么做的呢?
  BOOL CStdioFile::Open(LPCTSTR lpszFileName, UINT nOpenFlags, CFileException* pException) 
  {
   …
   /// 调用基类打开文件,注意通过nOpenFlags & ~typeText过滤了文件的文本属性
   if (!CFile::Open(lpszFileName, (nOpenFlags & ~typeText), pException))
   return FALSE;
   …
  ///转换找开模式
  if (nOpenFlags & typeBinary)
   szMode[nMode++] = 'b', nFlags ^= _O_TEXT;
   else
   szMode[nMode++] = 't';
   …
   // open a C-runtime low-level file handle
   int nHandle = _open_osfhandle((UINT_PTR) m_hFile, nFlags);
   // open a C-runtime stream from that handle
   if (nHandle != -1)
   m_pStream = _fdopen(nHandle, szMode);
   …
  }
   由上面的代码可以看出,CStdioFile强制过滤了typeText标志,使得文件打开模式可以是二进制模式。这已经可以证明CStdioFile不是一个纯粹TextFile类。
   再仔细看上面的代码,在调用基类打开后,又使用_open_osfhandle和_fdopen做了奇怪的转换,察看m_pStream的类型 
   FILE* m_pStream; // stdio FILE
   这是一个标准I/O的FILE结构。如果再进一步的研究CStdioFile的源码,还会发现它都是调用标准I/O的函数来操作的,比如用_fputts/_fgetts来实现WriteString/ReadString,用fread/fwrite/fseek来替代Read/Write/Seek。注意CStdioFile并没有使用CFile的Read/Write/Seek函数,如果在Open里将使用fopen直接打开的话,CStdioFile甚至可以说和CFile没有任何的关系。,由此这个类叫做CStdioFile就不奇怪了。
   为什么要研究这个问题呢?前一段在csdn.net上看到不少人问为什么UNICODE的文本文件处理出现乱码?他们很惊异发现平常作为TextFile的处理类用得CStdioFile竟然失效了。真的是它失效了吗?其实是标准的I/O操作并不支持UNICODE的模式而已。
原创粉丝点击