标签:自定义函数库
 自定义的常用文件与目录操作函数库,在win和linux平台做了跨平台的处理。(跨平台的处理可以作为参考比较。在win下目录的符号可以是\或者/,但是在linux下只能是/。)
下面给出的是源文件,实现接口函数的代码。每个接口函数都有很详细的功能说明。
/* 判断文件或目录是否存在bool FileUtil::FileExists(LPCTSTR sFilePath)
{
#if PLATFORM == WINDOWS32 || PLATFORM == WINDOWS64
	DWORD dwAttr = GetFileAttributes(sFilePath);
	if ( dwAttr == (DWORD)-1 )
		return false;
	else return true;
#endif
#if PLATFORM == LINUX32 || PLATFORM == LINUX64
	struct stat file;
	int res = stat(sFilePath, &file);
	if(-1 != res && S_ISREG(file.st_mode))
	{
		return true;
	}
	else return false;
#endif
}bool FileUtil::IsArchive(LPCTSTR sFilePath)
{
#if PLATFORM == WINDOWS32 || PLATFORM == WINDOWS64
	DWORD dwAttr = GetFileAttributes(sFilePath);
	if ( dwAttr == (DWORD)-1 || (dwAttr & FILE_ATTRIBUTE_ARCHIVE) == 0 )
		return false;
	else return true;
#endif
#if PLATFORM == LINUX32 || PLATFORM == LINUX64
	//简单判断文件是否存在
	struct stat file;
	int res = stat(sFilePath, &file);
	if(-1 != res && S_ISREG(file.st_mode))
	{
		return true;
	}
	else return false;
#endif
}bool FileUtil::IsDirectory(LPCTSTR sDirPath)
{
#if PLATFORM == WINDOWS32 || PLATFORM == WINDOWS64
	DWORD dwAttr = GetFileAttributes(sDirPath);
	if ( dwAttr == (DWORD)-1 || (dwAttr & FILE_ATTRIBUTE_DIRECTORY) == 0 )
		return false;
	else return true;
#endif
#if PLATFORM == LINUX32 || PLATFORM == LINUX64
	struct stat file;
	int res = stat(sDirPath, &file);
	if(-1 != res && S_ISDIR(file.st_mode))
	{
		return true;
	}
	return false;
#endif
}SIZE_T FileUtil::ExtractFileName(LPCTSTR sFilePath, LPTSTR sNameBuf, SIZE_T dwBufLen)
{
	LPCTSTR sNameStart, sNameEnd = sFilePath + _tcslen(sFilePath) - 1;
	//跳过目录名称后连续的'/'或'\'
	while ( sNameEnd >= sFilePath && (*sNameEnd == '/' || *sNameEnd == '\\') )
	{
		sNameEnd--;
	}
	sNameStart = sNameEnd;
	sNameEnd++;
	//定位目录名称起始的位置
	while ( sNameStart >= sFilePath )
	{
		if ( *sNameStart == '/' || *sNameStart == '\\' )
			break;
		sNameStart--;
	}
	sNameStart++;
	//拷贝目录名称
	if ( sNameStart < sNameEnd )
	{
		SIZE_T dwNameLen = sNameEnd - sNameStart;
		if ( dwBufLen > 0 )
		{
			if ( dwBufLen > dwNameLen )
				dwBufLen = dwNameLen;
			else dwBufLen--;
			memcpy(sNameBuf, sNameStart, sizeof(*sNameStart) * dwBufLen);
			sNameBuf[dwBufLen] = 0;
		}
		return dwNameLen;
	}
	return 0;
}SIZE_T FileUtil::ExtractFileNameOnly(LPCTSTR sFileName, LPTSTR sNameBuf, SIZE_T dwBufLen)
{
	//文件名为空则直接返回0
	if ( !*sFileName )
	{
		if ( dwBufLen > 0 )
			sNameBuf[0] = 0;
		return 0;
	}
	LPCTSTR sNameStart, sNameEnd = sFileName + _tcslen(sFileName) - 1;
	//如果文件是目录
	if ( *sNameEnd == '/' || *sNameEnd == '\\' )
	{
		//跳过目录名称后连续的'/'或'\'
		while ( sNameEnd >= sFileName && (*sNameEnd == '/' || *sNameEnd == '\\') )
		{
			sNameEnd--;
		}
		sNameEnd++;
	}
	else
	{
		LPCTSTR sPtr = sNameEnd;
		//找到文件后缀部分的起始位置
		while ( sPtr >= sFileName )
		{
			if (*sPtr == '.')
			{
				sNameEnd = sPtr;
				break;
			}
			if (*sPtr == '/' || *sPtr == '\\')
				break;
		}
	}
	sNameStart = sNameEnd - 1;
	//定位目录名称起始的位置
	while ( sNameStart >= sFileName )
	{
		if ( *sNameStart == '/' || *sNameStart == '\\' )
			break;
		sNameStart--;
	}
	sNameStart++;
	//拷贝目录名称
	if ( sNameStart < sNameEnd )
	{
		SIZE_T dwNameLen = sNameEnd - sNameStart;
		if ( dwBufLen > 0 )
		{
			if ( dwBufLen > dwNameLen )
				dwBufLen = dwNameLen;
			else dwBufLen--;
			memcpy(sNameBuf, sNameStart, sizeof(*sNameStart) * dwBufLen);
			sNameBuf[dwBufLen] = 0;
		}
		return dwNameLen;
	}
	return 0;
}LPCTSTR FileUtil::ExtractFileExt(LPCTSTR sFileName)
{
	LPCTSTR sResult = NULL;
	while (*sFileName)
	{
		if (*sFileName == '.')
			sResult = sFileName;
		sFileName++;
	}
	return sResult;
}SIZE_T FileUtil::ExtractFileDirectory(LPCTSTR sFilePath, LPTSTR sDirBuf, SIZE_T dwBufLen)
{
	LPCTSTR sDirEnd = sFilePath + _tcslen(sFilePath) - 1;
	while (sDirEnd >= sFilePath && *sDirEnd != '/' && *sDirEnd != '\\')
	{
		sDirEnd--;
	}
	if ( sDirEnd > sFilePath )
	{
		SIZE_T dwNameLen = sDirEnd - sFilePath;
		if ( dwBufLen > 0 )
		{
			if ( dwBufLen > dwNameLen )
				dwBufLen = dwNameLen;
			else dwBufLen--;
			memcpy(sDirBuf, sFilePath, sizeof(*sDirBuf) * dwBufLen);
			sDirBuf[dwBufLen] = 0;
		}
		return dwNameLen;
	}
	return 0;
}SIZE_T FileUtil::ExtractTopDirectoryName(LPCTSTR sDirPath, OUT LPCTSTR *ppChildDirPath, LPTSTR sDirName, SIZE_T dwBufLen)
{
	LPCTSTR sNameEnd;
	//跳过目录名称前连续的'/'或'\'
	while ( *sDirPath && (*sDirPath == '/' || *sDirPath == '\\') )
	{
		sDirPath++;
	}
	sNameEnd = sDirPath;
	//定位目录名称起始的位置
	while ( *sNameEnd )
	{
		if ( *sNameEnd == '/' || *sNameEnd == '\\' )
			break;
		sNameEnd++;
	}
	//拷贝目录名称
	if ( sNameEnd > sDirPath )
	{
		SIZE_T dwNameLen = sNameEnd - sDirPath;
		if ( dwBufLen > 0 )
		{
			if ( dwBufLen > dwNameLen )
				dwBufLen = dwNameLen;
			else dwBufLen--;
			memcpy(sDirName, sDirPath, sizeof(*sDirPath) * dwBufLen);
			sDirName[dwBufLen] = 0;
			if (ppChildDirPath)
				*ppChildDirPath = sNameEnd;
		}
		return dwNameLen;
	}
	return 0;
}bool FileUtil::DeepCreateDirectory(LPCTSTR sDirPath)
{
	TCHAR sPath[4096];
	LPTSTR sPathPtr = sPath;
	SIZE_T dwNameLen, dwBufLen = ArrayCount(sPath) - 1;
	DWORD dwAttr;
	while (true)
	{
		dwNameLen = ExtractTopDirectoryName(sDirPath, &sDirPath, sPathPtr, dwBufLen);//获取顶层目录名称* (abc\efg\ --> abc)
		//如果目录名称长度超过目录缓冲区长度则放弃
		if ( dwNameLen >= dwBufLen )
			return false;
		//如果目录名称长度为0则表示所有目录均已创建完成
		if (dwNameLen == 0)
			return true;
		sPathPtr += dwNameLen;
#if PLATFORM == WINDOWS32 || PLATFORM == WINDOWS64
		//如果目录名称不是驱动器名称则检查和创建目录
		if (sPathPtr[-1] != ':')
		{
			//如果目录不存在则创建此目录
			dwAttr = GetFileAttributes(sPath);
			if ( (dwAttr == (DWORD)-1 && GetLastError() == ERROR_FILE_NOT_FOUND) )
			{
				if (!CreateDirectory(sPath, NULL))
					return false;
			}
			//如果文件存在且文件不是目录则返回false
			else if ( !(dwAttr & FILE_ATTRIBUTE_DIRECTORY) )
			{
				return false;
			}
		}
#endif
#if PLATFORM == LINUX32 || PLATFORM == LINUX64
		struct stat fileStat;
		if(-1 == stat(sPath, &fileStat))//没有该文件或目录
		{
			if(ENOENT == errno)//错误码是 ENOENT: No such file or directory 
			{
				if(-1 == mkdir(sPath, S_IRWXG))//创建一层目录
				{
					return false;
				}
			}
		}
#endif
		sPathPtr[0] = '/';
		sPathPtr++;
		if ( dwBufLen > dwNameLen )
			dwBufLen -= dwNameLen + 1;
		else dwBufLen = 0;
	}
	return false;
}其中的一些自定义的宏定义和类型定义如下:
由于跨平台的原因的自定义宏(使用时,没有跨平台需要的话,可删除不需要的部分)
#define _tcslen(STR) strlen(STR)
typedef const char *LPCTSTR, *LPCSTR;
typedef size_t SIZE_T;
其他的宏
获取数组长度
#define ArrayCount(a)(sizeof(a)/sizeof((a)[0]))
标签:自定义函数库
原文地址:http://blog.csdn.net/chenjiayi_yun/article/details/44751081