WIndows API函数CreateFile和CreateDirectory用于创建文件和目录,但设想这样一种情况:需要创建文件C:\test\test.txt,但是C:\test\目录不存在,简单地调用CreateFile不会成功了,创建目录也是一样。
我在Windows API找了很久,没找到能满足要求的函数,Shell API里也没有,于是只能靠自己实现了。
传入目录时,有些人习惯于在尾部加反斜杠,有些又没加反斜杠,为了方便编程,先封装一个方法来规范一下:
//
若bAddSpec 为真,则确保szDst路径末尾带有"\", 若bAddSpec为假,则去除lpszPath末尾的"\"或"/"
template
<
size_t nSize
>
inline
void
ModifyPathSpec( TCHAR (
&
szDst)[nSize], BOOL bAddSpec )
{
int
nLen
=
lstrlen( szDst );
ASSERT( nLen
>
0
);
TCHAR ch
=
szDst[ nLen
-
1
];
if
( ( ch
==
_T(
'
\\
'
) )
||
( ch
==
_T(
'
/
'
) ) )
{
if
(
!
bAddSpec )
{
szDst[ nLen
-
1
]
=
_T(
'
\0
'
);
}
}
else
{
if
( bAddSpec )
{
szDst[ nLen ]
=
_T(
'
\\
'
);
szDst[ nLen
+
1
]
=
_T(
'
\0
'
);
}
}
}
首先讨论创建文件夹的情况,创建文件夹时主要是个递归过程,首先判断上级目录是否存在,
如果不存在,则递归创建上级目录.代码如下:
//
嵌套创建文件夹
inline BOOL CreateDirectoryNested( LPCTSTR lpszDir )
{
if
( ::PathIsDirectory( lpszDir ) )
return
TRUE;
TCHAR szPreDir[ MAX_PATH ];
_tcscpy_s( szPreDir, lpszDir );
//
确保路径末尾没有反斜杠
ModifyPathSpec( szPreDir, FALSE );
//
获取上级目录
BOOL bGetPreDir
=
::PathRemoveFileSpec( szPreDir );
if
(
!
bGetPreDir )
return
FALSE;
//
如果上级目录不存在,则递归创建上级目录
if
(
!
::PathIsDirectory( szPreDir ) )
{
CreateDirectoryNested( szPreDir );
}
return
::CreateDirectory( lpszDir, NULL );
}
创建文件目录后,直接调用CreateFile就可以创建文件了.代码如下:
//
嵌套创建文件,bOverride为TRUE表示覆盖原已存在的文件
inline BOOL CreateFileNested( LPCTSTR lpszFile, BOOL bOverride
=
TRUE )
{
if
( ::PathFileExists( lpszFile ) )
return
TRUE;
TCHAR szDir[ MAX_PATH ];
_tcscpy_s( szDir, lpszFile );
//
获取文件目录
BOOL bGetDir
=
::PathRemoveFileSpec( szDir );
if
(
!
bGetDir )
return
FALSE;
//
创建文件目录
if
(
!
CreateDirectoryNested( szDir ) )
return
FALSE;
DWORD dwCreate
=
bOverride
?
CREATE_ALWAYS:OPEN_ALWAYS;
HANDLE hFile
=
::CreateFile( lpszFile, GENERIC_READ
|
GENERIC_WRITE, FILE_SHARE_READ
|
FILE_SHARE_WRITE, NULL,
dwCreate, FILE_FLAG_BACKUP_SEMANTICS, NULL );
if
( hFile
==
INVALID_HANDLE_VALUE)
return
FALSE;
::CloseHandle( hFile );
return
TRUE;
}