[原创] 在MFC中大家都习惯用CStdioFile来处理文本文件,可是为什么CStdioFile不叫CTextFile?
2004-10-03 12:16
405 查看
这个恐怕是一个很奇怪的问题,甚至我在csdn.net上发帖的时候,有人这样回答“因为如果叫成CTextFile,你肯定要问 CTextFile为什么不叫CStdioFile?”。
也有人比较认真的说“CStdioFile类既可以对文本文件进行操作也可以对二进制文件进行操作,他有Write(),Read()等方法,而不公是WriteString(),ReadString()。很明显不能叫CTextFile,看名字会认识是专门对文件文件进行访问的”。的确,类库的类名都是经过认真确认以保证能够正确描述类的功能,但作为一个继承类关键是要说明新添加的功能(基类的功能肯定是要继承来的),所以上面的说法未免有点牵强。
要说为什么,首先我们要看看什么是TextFile。我们都知道在CFile类中提供了2种模式,typeBinary和typeText。如果是CTextFile类的话当然要强制使用typeText类型了。那么CStdioFile是怎么做的呢?<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
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的模式而已。
也有人比较认真的说“CStdioFile类既可以对文本文件进行操作也可以对二进制文件进行操作,他有Write(),Read()等方法,而不公是WriteString(),ReadString()。很明显不能叫CTextFile,看名字会认识是专门对文件文件进行访问的”。的确,类库的类名都是经过认真确认以保证能够正确描述类的功能,但作为一个继承类关键是要说明新添加的功能(基类的功能肯定是要继承来的),所以上面的说法未免有点牵强。
要说为什么,首先我们要看看什么是TextFile。我们都知道在CFile类中提供了2种模式,typeBinary和typeText。如果是CTextFile类的话当然要强制使用typeText类型了。那么CStdioFile是怎么做的呢?<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
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的模式而已。
相关文章推荐
- 【原创】多字节版本下MFC控件处理字符集的BUG
- 写了一个简单的处理类似xml文件的类,请大家指正【原创】
- MFC中CStdioFile处理文本文件乱码的
- [原创]MFC中的多线程处理问题总结
- [原创]PowerShell处理文本文件
- stdafx.h、stdafx.cpp是干什么用的?为什么我的每一个cpp文件都必须包含stdafx.h? Windows和MFC的include文件都非常大,即使有一个快速的处理程序,编
- CStdioFile,CFile类,文本文件处理(MFC学习园地)
- FileHelper 一个极好的数据文本文件处理类库
- VS2012 MFC CStdioFile ReadString 处理UTF8文档乱码的方法
- [原创]MFC中的多线程处理问题总结
- stdafx.h、stdafx.cpp是干什么用的?为什么我的每一个cpp文件都必须包含stdafx.h? Windows和MFC的include文件都非常大,即使有一个快速的处理程序,编
- 【转载】MFC中SDI、MDI框架各部分指针获取(网上找的,好东西大家一起分享,多谢原创作者!)
- VBA使用FileSystemObject将读取或写入文本文件(三)
- DriveInfo Directory File类和FileInfo类知识点 文本文件操作
- 『原创』用C++开发WM应用系列(4)——处理屏幕旋转
- 转载 ----MFC动态创建控件的消息处理
- 用MFC实现的简单的集合运算程序(原创)
- 【Vegas原创】“無法解析 equal to 動作的定序衝突”错误的处理
- Hadoop MapReduce处理海量小文件:基于CombineFileInputFormat(每次往map中读入1行)
- spring错误处理 Build path is incomplete. Cannot find class file for org.springframework.aop.Advisor