工作中遇到的问题:文件操作函数与资源管理器
1)BOOL CreateDirectory( LPCTSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes );描述:只能创建空白目录,且当前目录下没有同名文件夹。参数:lpPathName长度最大247,格式可以是本地绝对路径或者是8.3路径加文件名或者UNC路径,使用UNICODE编码并且加上前缀可以扩展到32767(详见http://msdn.microsoft.com/en-us/library/windows/desktop/aa36524(v=vs.85).aspx)。
2)BOOL RemoveDirectory( LPCTSTR lpPathName );描述:删除空文件。参数:同上.
3)BOOL DeleteFile( LPCTSTR lpFileName );描述:删除文件。
4)BOOL PathIsDirectory( LPCTSTR pszPath );描述:判断一个路径是否是一个目录。参数:pszPath最大长度MAX_PATH,这个路径长度可以达到259,win7和xp都可以。
5)BOOL PathFileExists( LPCTSTR pszPath );描述:判断一个文件或者文件夹是否存在。参数:同PathIsDirectory。
6)LPTSTR PathFindFileName( LPCTSTR pPath );描述:取得文件名。pPath长度限制MAX_PATH(win7下很长也可以成功,未知道原因)。
7)LPTSTR PathFindExtension( LPCTSTR pPath );描述:取得扩展名。pPath同PathFindFileName。
8)virtual BOOL CFileFind::FindFile( LPCTSTR pstrName = NULL, DWORD dwUnused = 0 );描述:调用此函数开始文件搜索。
参数:pstrName最大长度MAX_PATH(包括结尾的'\*.*'(也可以是'\\*.*'),只要当前pstrName小于MAX_PATH,当前目录下的文件都可以遍历的到。
9)WINSHELLAPI DWORD WINAPI SHGetFileInfo( LPCTSTR pszPath, DWORD dwFileAttributes, SHFILEINFO FAR* psfi, UINT cbFileInfo, UINT uFlags );描述:这个函数获取文件系统中一个对象的信息,如文件、文件夹、一个目录或一个驱动器根。
参数:pszPath不支持加前缀;当第二个参数为0时,win7下测试没有长度限制,但是xp下超过MAX_PATH会失败( SHGetFileInfo(pszPath,0,&sfi,sizeof(sif),SHGFI_SYSICONINDEX)要获取系统图表索引 )。
dwFileAttributes文件属性标志,FILE_ATTRIBUTE_NORMAL通过扩展名获取图标索引,不可以获取文件夹索引;FILE_ATTRIBUTE_DIRECTORY获取文件夹图表索引;当设置这个参数时,pszPath没有长度限制(win7和xp,但是设置为空有时可能出错)。
项目是类似资源管理器的程序,想通过给定的路径,取得路径下的文件名和图标显示到Clistctrl中。
>>流程:得到strPath(用到的是UNC路径\\192.168.100.100\....),如果PathIsDirectory为true,通过CFileFind类找到文件名,通过SHGetFileInfo取得系统图标索引。
>>问题:当strPath长度Len(不包括结尾'\0'),0<=Len<=254时正常执行;当Len=255时,PathIsDirectory正常,CFileFind参数为strPath加上结尾的'\*.*',长度为259,运行时内存错误,下面分析原因;256<=Len<=259时PathIsDirectory正常,CFileFind参数检查大于等于WIN32_FIND_DATA结构的CFileName长度,返回FALSE,我们可以根据返回值做处理。
>>分析原因:len=255,参数检查长度没有错误,继续执行。调用::FindFirstFile,最后检查路径组成的有效性
1-> TCHAR strDrive[_MAX_DRIVE], strDir[_MAX_DIR];
2-> Checked::tsplitpath_s(pstrRoot, strDrive, _MAX_DRIVE, strDir, _MAX_DIR, NULL, 0, NULL, 0);
3-> Checked::tmakepath_s(pstrRoot, _MAX_PATH, strDrive, strDir, NULL, NULL);
4-> m_strRoot.ReleaseBuffer(-1);
其中_MAX_DIR=256,出错在第二句,因为路径使用的是UNC路径,所以全部的路径全部放到缓存strDir中,而且还要加上最后的'\',最后长度应该是255+1,strDir没有空间放最后的'\0'了,报内存错误,很疑惑为什么没有报缓存区不够,设置ErrorNum,而是直接弹出内存错误。
>>解决问题:未解决,我将大于等于255情况在CFileFind::FindFile之前做了一下判断,将大于等于255情况做了一样的处理。