无语的CAtlTemporaryFile类
经常需要将一些内容写进临时文件,这就需要结合GetTempPath和GetTempFileName在Windows临时目录下生成一个临时文件。ATL提供了类CAtlTemporaryFile来进行这层封装,可使用此类时,才发现该类有多么地鸡肋啊.我写了一个Demo:
CAtlTemporaryFile fileTmp;
fileTmp.Create();
fileTmp.Write( COLE2CT( bstrHtml ), wcslen( bstrHtml ) );
fileTmp.Close( );
![](https://www.cnblogs.com/Images/dot.gif)
fileTmp.TempFileName();
fileTmp.Create();
fileTmp.Write( COLE2CT( bstrHtml ), wcslen( bstrHtml ) );
fileTmp.Close( );
![](https://www.cnblogs.com/Images/dot.gif)
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;
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;