自定义的常用文件与目录操作函数库

 自定义的常用文件与目录操作函数库,在win和linux平台做了跨平台的处理。(跨平台的处理可以作为参考比较。在win下目录的符号可以是\或者/,但是在linux下只能是/。)

 下面给出的是源文件,实现接口函数的代码。每个接口函数都有很详细的功能说明。

/* 判断文件或目录是否存在
* 在操作系统中,目录也是一个文件,如果要判断一个目录是否存在则应当使用DirectoryExists,
* 要判断一个文件是否存在且是一个归档文件则应当使用IsArchive。
* @如果文件或目录存在则返回true否则返回false
* %文件路径字符长度不得超过MAX_PATH
*/
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
}

/* 判断文件是否存在且是一个可直接读取的归档文件(比如自定义的文本文件或者txt文件等)
 * %文件路径字符长度不得超过MAX_PATH
*/
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
}

/* 判断目录是否存在,文件存在且文件是一个目录则返回true否则返回false
 * %文件路径字符长度不得超过MAX_PATH
 */
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
}

/* 获取文件或目录名称
 * c:\abc\123.txt --> 123.txt
 * c:\abc\efg\ --> efg
 * 参数sDirBuf用于存储文件名称字符串
 * 参数dwBufLen为sNameBuf参数的缓冲区字符(非字节)长度,其中含需要保留的终止字符,
    如果dwBufLen值为0则函数不会将文件名拷贝到sNameBuf中;
    如果dwBufLen值非0则函数会将文件名拷贝到sNameBuf中并会在sNameBuf中写入终止符;
    如果缓冲区不够则只拷贝dwBufLen-1个字符并会在sNameBuf中写入终止符。
@函数返回拷贝文件名所需的字符长度(含终止符)
*/
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;
}


/* 获取文件路径中的文件名部分,不包含文件后缀部分
 * c:\abc.txt --> abc
 * 参数sNameBuf用于存储文件名称字符串
 * 参数dwBufLen为sNameBuf参数的缓冲区字符(非字节)长度,其中含需要保留的终止字符,
    如果dwBufLen值为0则函数不会将文件名拷贝到sNameBuf中;
    如果dwBufLen值非0则函数会将文件名拷贝到sNameBuf中并会在sNameBuf中写入终止符;
    如果缓冲区不够则只拷贝dwBufLen-1个字符并会在sNameBuf中写入终止符。
@函数返回拷贝文件名所需的字符长度(含终止符)
*/
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;
}

/* 获取文件名或文件路径中的文件后缀部分
 * abc.txt --> .txt
 * 返回值包含后缀符号'.'
 */
LPCTSTR FileUtil::ExtractFileExt(LPCTSTR sFileName)
{
	LPCTSTR sResult = NULL;
	while (*sFileName)
	{
		if (*sFileName == '.')
			sResult = sFileName;
		sFileName++;
	}
	return sResult;
}

/* 获取文件所在目录路径
     * c:\abc\efg\123.txt --> c:\abc\efg\
 * c:\abc\efg\ --> c:\abc\
 * 参数sDirBuf用于存储目录字符串
 * 参数dwBufLen为sDirName参数的缓冲区字符(非字节)长度,其中含需要保留的终止字符,
       如果dwBufLen值为0则函数不会将目录路径拷贝到sDirBuf中;
   如果dwBufLen值非0则函数会将目录路径拷贝到sDirBuf中并会在sDirBuf中写入终止符;
   如果缓冲区不够则只拷贝dwBufLen-1个字符并会在sDirBuf中写入终止符。
@函数返回拷贝目录路径所需的字符长度(含终止符)
 */
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;
}


/* 获取顶层目录名称
 * (abc\efg\ --> abc)
 * 参数ppChildDirPath用于存顶层目录之后的目录路径,参数可以为空
 * 参数sDirName用于存储目录字符串
 * 参数dwBufLen为sDirName参数的缓冲区字符(非字节)长度,其中含需要保留的终止字符,
       如果dwBufLen值为0则函数不会将目录名拷贝到sDirName中;
   如果dwBufLen值非0则函数会将目录名拷贝到sDirName中并会在sDirName中写入终止符;
   如果缓冲区不够则只拷贝dwBufLen-1个字符并会在sDirName中写入终止符。
@函数返回拷贝目录名所需的字符长度(含终止符)
 */
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;
}


/* 逐层创建目录
 * 如果创建目录C:\a\b\c\d,最终目录的父目录不存在则逐级创建父目录并创建最终目录
 * @如果目录完全创建成功则函数返回true,否则返回false。
 * %如果在创建某个父目录成功后并创建子目录失败,则函数返回false且已经创建的父目录不会被删除。
 * %目录路径的总体字符长度,函数要求必须在MAX_PATH个字符长度以内
 */
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]))

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值