我正在使用Visual C ++ 2010& MFC写了一个小程序。
以下是我的代码:
CFile MyFile;
CFileException* pException = NULL;
CString strErrorMessage;
// The Test.txt is a hidden file that I created already.
if (!MyFile.Open(_T("E:\\Test.txt"), CFile::modeWrite | CFile::modeCreate, pException))
{
TCHAR lpCause[255];
pException->GetErrorMessage(lpCause, 255);
strErrorMessage += lpCause;
}
// ...
// rewrite the Test.txt
// ...
MyFile.Close();
以下是我的问题:
1.运行代码时,会出现未处理的异常。那么如何修改代码才能使其正常工作?
2.我尝试删除Test.txt隐藏文件属性,似乎运行良好。我想知道:为什么文件隐藏属性的文件(已存在)无法在创建和写入模式下打开?
感谢。
答案 0 :(得分:3)
pException
仅初始化为NULL
,未分配。您应该分配它,或者只是声明CFileException exception;
并传递地址&exception
。另外,如果CFile::Open
失败,请勿尝试关闭文件。
CFile的文档说不要将CFile::modeCreate
用于现有文件,因为它会引发异常。推理并不完全正确。
在Visual Studio 15中,MFC的CFile::Open
源代码显示:
// map creation flags
if (nOpenFlags & modeCreate)
{
if (nOpenFlags & modeNoTruncate)
dwCreateFlag = OPEN_ALWAYS;
else
dwCreateFlag = CREATE_ALWAYS;
}
else
dwCreateFlag = OPEN_EXISTING;
...
CreateFile(... nOpenFlags ...)
CFile::modeCreate
(不modeNoTruncate
)在CREATE_ALWAYS
API中设置标记CreateFile
。 CreateFile的WinAPI文档说
如果指定了
CREATE_ALWAYS
和FILE_ATTRIBUTE_NORMAL
,CreateFile
如果文件失败,则将最后一个错误设置为ERROR_ACCESS_DENIED
已存在且有FILE_ATTRIBUTE_HIDDEN
或FILE_ATTRIBUTE_SYSTEM
属性。要避免错误,请指定与之相同的属性 现有文件。
这解释了为什么函数仅对存在和隐藏的文件失败。
要解决此问题,我们可以添加modeNoTruncate
以强制OPEN_ALWAYS
。如果需要,请使用CFile::SetLength(0)
截断文件。
CFile MyFile;
CFileException exception;
CString strErrorMessage;
CString filename = _T("e:\\Test.txt");
if(MyFile.Open(filename, CFile::modeWrite | CFile::modeCreate | CFile::modeNoTruncate,
&exception))
{
//SetLength(0) if file needs to truncate
MyFile.SetLength(0);
MyFile.Close();
}
else
{
TCHAR lpCause[255];
exception.GetErrorMessage(lpCause, 255);
strErrorMessage += lpCause;
}
或者,测试是否存在旧文件,如果文件不存在则添加CFile::modeCreate
。再后跟SetLength(0)
截断文件。
UINT flags = CFile::modeWrite;
if(!PathFileExists(filename))
flags |= CFile::modeCreate;
if (MyFile.Open(filename, flags, &exception))
{
MyFile.SetLength(0);
MyFile.Close();
}