[原创] 在MFC中大家都习惯用CStdioFile来处理文本文件,可是为什么CStdioFile不叫CTextFile?

    这个恐怕是一个很奇怪的问题,甚至我在csdn.net上发帖的时候,有人这样回答因为如果叫成CTextFile,你肯定要问 CTextFile为什么不叫CStdioFile

    
也有人比较认真的说“CStdioFile类既可以对文本文件进行操作也可以对二进制文件进行操作,他有Write(),Read()等方法,而不公是WriteString(),ReadString()。很明显不能叫CTextFile,看名字会认识是专门对文件文件进行访问的。的确,类库的类名都是经过认真确认以保证能够正确描述类的功能,但作为一个继承类关键是要说明新添加的功能(基类的功能肯定是要继承来的),所以上面的说法未免有点牵强。

    
要说为什么,首先我们要看看什么是TextFile。我们都知道在CFile类中提供了2种模式,typeBinarytypeText。如果是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/OFILE结构。如果再进一步的研究CStdioFile的源码,还会发现它都是调用标准I/O的函数来操作的,比如用_fputts/_fgetts来实现WriteString/ReadString,用fread/fwrite/fseek来替代Read/Write/Seek。注意CStdioFile并没有使用CFileRead/Write/Seek函数,如果在Open里将使用fopen直接打开的话,CStdioFile甚至可以说和CFile没有任何的关系。,由此这个类叫做CStdioFile就不奇怪了。


      
为什么要研究这个问题呢?前一段在csdn.net上看到不少人问为什么UNICODE的文本文件处理出现乱码?他们很惊异发现平常作为TextFile的处理类用得CStdioFile竟然失效了。真的是它失效了吗?其实是标准的I/O操作并不支持UNICODE的模式而已。

 

 

你可能感兴趣的:(Stream,File,mfc)