经常需要将一些内容写进临时文件,这就需要结合GetTempPath和GetTempFileName在Windows临时目录下生成一个临时文件。ATL提供了类CAtlTemporaryFile来进行这层封装,可使用此类时,才发现该类有多么地鸡肋啊.我写了一个Demo:
CAtlTemporaryFile fileTmp;
fileTmp.Create();
fileTmp.Write( COLE2CT( bstrHtml ), wcslen( bstrHtml ) );
fileTmp.Close( );

fileTmp.TempFileName();
照理说这样应该就可以了,但一直得不到我要的文件,跟踪CAtlTemporaryFile源码才发现在成员方法Close已经把生成的文件删除了.我纳闷了,这是啥意思嘛!还让不让人用啊。再一细看,发现Close方法提供了一个参数:szNewName,Close方法将生成的文件移动到szNewName指定的文件,若不指定,则直接删除生成的文件.由于Close方法移动前会删除szNewName指定的文件已确保其不存在,因此,我最后一个希望:将szNewName指定为CAtlTemporaryFile生成的文件(由TempFileName获取)也破灭了.真是悲剧了.让我重新指定一个目标文件地址,我还用CAtlTemporaryFile干嘛啊,真的简直是鸡肋.没办法,我只有定制CAtlTemporaryFile的源码了,还好该源码没有那么多的依赖关系,十分利于拷贝,哈哈.下面是我的修改版本:
#include
<
atlfile.h
>
template
<
bool
bDeleted
>
class
CAtlTemporaryFileExT
{
public
:
CAtlTemporaryFileExT()
throw
()
{
}
~
CAtlTemporaryFileExT()
throw
()
{
//
Ensure that the temporary file is closed and deleted,
//
if necessary.
if
(m_file.m_h
!=
NULL)
{
Close();
}
//
如果设为自动删除,结束时则删除文件
if
( bDeleted )
{
Delete();
}
}
HRESULT Create(__in_opt LPCTSTR pszDir
=
NULL, __in DWORD dwDesiredAccess
=
GENERIC_WRITE)
throw
()
{
TCHAR szPath[_MAX_PATH];
TCHAR tmpFileName[_MAX_PATH];
ATLASSUME(m_file.m_h
==
NULL);
if
(pszDir
==
NULL)
{
DWORD dwRet
=
GetTempPath(_MAX_DIR, szPath);
if
(dwRet
==
0
)
{
//
Couldn't find temporary path;
return
AtlHresultFromLastError();
}
else
if
(dwRet
>
_MAX_DIR)
{
return
DISP_E_BUFFERTOOSMALL;
}
}
else
{
if
(Checked::tcsncpy_s(szPath, _countof(szPath), pszDir, _TRUNCATE)
==
STRUNCATE)
{
return
DISP_E_BUFFERTOOSMALL;
}
}
if
(
!
GetTempFileName(szPath, _T(
"
TFR
"
),
0
, tmpFileName))
{
//
Couldn't create temporary filename;
return
AtlHresultFromLastError();
}
tmpFileName[_countof(tmpFileName)
-
1
]
=
'
\0
'
;
Checked::tcsncpy_s(m_szTempFileName, _countof(m_szTempFileName), tmpFileName, _TRUNCATE);
SECURITY_ATTRIBUTES secatt;
secatt.nLength
=
sizeof
(secatt);
secatt.lpSecurityDescriptor
=
NULL;
secatt.bInheritHandle
=
TRUE;
m_dwAccess
=
dwDesiredAccess;
return
m_file.Create(
m_szTempFileName,
m_dwAccess,
0
,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED
|
FILE_ATTRIBUTE_TEMPORARY,
&
secatt);
}
HRESULT Close()
throw
()
{
ATLASSUME(m_file.m_h
!=
NULL);
m_file.Close();
return
S_OK;
}
HRESULT Delete()
{
return
::DeleteFile( m_szTempFileName )
?
S_OK : S_FALSE;
}
HRESULT HandsOff()
throw
()
{
m_file.Flush();
m_file.Close();
return
S_OK;
}
HRESULT HandsOn()
throw
()
{
HRESULT hr
=
m_file.Create(
m_szTempFileName,
m_dwAccess,
0
,
OPEN_EXISTING);
if
(FAILED(hr))
return
hr;
return
m_file.Seek(
0
, FILE_END);
}
HRESULT Read(
__out_bcount(nBufSize) LPVOID pBuffer,
__in DWORD nBufSize,
__out DWORD
&
nBytesRead)
throw
()
{
return
m_file.Read(pBuffer, nBufSize, nBytesRead);
}
HRESULT Write(
__in_bcount(nBufSize) LPCVOID pBuffer,
__in DWORD nBufSize,
__out_opt DWORD
*
pnBytesWritten
=
NULL)
throw
()
{
return
m_file.Write(pBuffer, nBufSize, pnBytesWritten);
}
HRESULT Seek(__in LONGLONG nOffset, __in DWORD dwFrom
=
FILE_CURRENT)
throw
()
{
return
m_file.Seek(nOffset, dwFrom);
}
HRESULT GetPosition(__out ULONGLONG
&
nPos)
const
throw
()
{
return
m_file.GetPosition(nPos);
}
HRESULT Flush()
throw
()
{
return
m_file.Flush();
}
HRESULT LockRange(__in ULONGLONG nPos, __in ULONGLONG nCount)
throw
()
{
return
m_file.LockRange(nPos, nCount);
}
HRESULT UnlockRange(__in ULONGLONG nPos, __in ULONGLONG nCount)
throw
()
{
return
m_file.UnlockRange(nPos, nCount);
}
HRESULT SetSize(__in ULONGLONG nNewLen)
throw
()
{
return
m_file.SetSize(nNewLen);
}
HRESULT GetSize(__out ULONGLONG
&
nLen)
const
throw
()
{
return
m_file.GetSize(nLen);
}
operator
HANDLE()
throw
()
{
return
m_file;
}
LPCTSTR TempFileName()
throw
()
{
return
m_szTempFileName;
}
private
:
CAtlFile m_file;
TCHAR m_szTempFileName[_MAX_FNAME
+
1
];
DWORD m_dwAccess;
};
typedef CAtlTemporaryFileExT
<
false
>
CAtlTemporaryFileEx;
//
自动删除版本
typedef CAtlTemporaryFileExT
<
true
>
CAtlTemporaryFileExHandle;