为什么隐藏文件无法在 MFC 中的创建和写入模式下打开?

Why hidden file can't be open in create and write mode in MFC?

本文关键字:模式 创建 隐藏文件 MFC 为什么      更新时间:2023-10-16

我正在使用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隐藏文件属性,它似乎工作得很好。我想知道:为什么具有文件隐藏属性的文件(存在)无法在创建和写入模式下打开?

谢谢。

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)在 API 中设置标志CREATE_ALWAYSCreateFile。WinAPI 文档 for CreateFile 说

如果指定了CREATE_ALWAYSFILE_ATTRIBUTE_NORMAL,则CreateFile失败并将最后一个错误设置为ERROR_ACCESS_DENIED如果文件出现 存在并具有FILE_ATTRIBUTE_HIDDENFILE_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();
}