C/C++ Windows和Linux通用的一个函数,从文件路径中 提取 (文件名) 和 (文件后缀)

Posted cpp_learners

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C/C++ Windows和Linux通用的一个函数,从文件路径中 提取 (文件名) 和 (文件后缀)相关的知识,希望对你有一定的参考价值。

假如给你一个文件路径,你可以将其中的文件名和文件后缀提取出来嘛?
不会没有关系,此篇博客提供一个函数,即可在Windows环境下调用,也可以在Linux环境下调用,去获取一个文件路径的文件名和文件后缀!


一、返回值 bool 版

需要包含头文件:
#include <stdio.h>
#include <string.h>
#include <string>

代码如下:

/******************************************************************************
 *
 * 功能:
 *		获得 (文件名.后缀) 和 (文件名) 和 (文件后缀),Windows和Linux通用!
 *
 * 参数:
 *		_filePaht:C语言字符指针,文件路径字符串
 *		_fileName:C++字符串引用,获得[(文件名.后缀)|(文件名)]返回
 *		_fileName:C++字符串引用,获得(文件名.后缀)返回
 *		_fileSuffix:C++字符串引用,获得(后缀)返回
 *		_dot:true,后缀带点(.txt);false,后缀不带点(txt);默认值为true
 *
 * 返回值:
 *		成功返回true,失败返回false
 *
 ******************************************************************************/
bool get_fileName_fileSuffix(const char *_filePaht, std::string &_fileNames, std::string &_fileName, std::string &_fileSuffix, bool _dot = true) 

	// 合法性检查
	if (!_filePaht) return false;
	std::string str = _filePaht;
	if (str.empty()) return false;


	// .txt    的情况
	if (str.at(0) == '.') return false;
	// file.   的情况
	if (str.at(str.size() - 1) == '.') return false;
	

	char c = '\\0';

// 区分此函数是在Windows环境调用还是Linux环境调用
#if defined (_WIN64) || defined (WIN32) || defined (_WIN32)
	//printf("---Windows---\\n");
	c = '\\\\';
#else
	//printf("---Linux---\\n");
	c = '\\/';
#endif

	// 去除字符串中的路径,剩下文件名
	std::string filename = strrchr(_filePaht, c) == NULL ? "" : strrchr(_filePaht, c) + 1;
	if (filename == "") 
		/* 说明字符串是file.txt或者file形式 */
		filename = _filePaht;
	
	 else 
		/* 说名字符串是C:\\\\abc\\\\file.txt或者C:\\\\abc\\\\file形式 */
	

	// 找到 . 的位置
	size_t _size = filename.rfind(".");
	// 获得文件名,不包含后缀
	_fileName = filename.substr(0, _size);

	// 获得文件后缀
	std::string strsuffix = "";
	if (_size != -1) 	// 不等于-1说明有后缀 file.txt形式

		// true后缀带点,false后缀不带点
		if (_dot == true) 
			strsuffix = filename.substr(_size);     // 文件后缀 .txt

		 else 
			strsuffix = filename.substr(_size + 1);     // 文件后缀 txt
		
	
	// 后缀
	_fileSuffix = strsuffix;

	// 获得文件名.后缀(file.txt | file)
	_fileNames = filename;

	return true;

具体过程就不解释了,都有详细注释,去看,去理解吧。

  1. 测试Windows路径:
    C:\\abc\\file.txt
    C:\\abc\\file
    file.txt
    file

    int main(void) 
    
    	// C:\\\\abc\\\\file.txt
    	// C:\\\\abc\\\\file
    	// file.txt
    	// file
    
    	std::string fileNames = "";
    	std::string fileName = "";
    	std::string fileSuffix = "";
    	bool suffix = true;
    	bool flag = false;
    
    	//printf("---Windows---\\n");
    
    	flag = get_fileName_fileSuffix("C:\\\\abc\\\\file.txt", fileNames, fileName, fileSuffix, suffix);
    	printf("str = %s, fileNames = %s   fileName = %s   fileSuffix = %s   flag = %d\\n\\n", "C:\\\\abc\\\\file.txt", fileNames.c_str(), fileName.c_str(), fileSuffix.c_str(), flag);
    
    	flag = get_fileName_fileSuffix("C:\\\\abc\\\\file", fileNames, fileName, fileSuffix, suffix);
    	printf("str = %s, fileNames = %s   fileName = %s   fileSuffix = %s   flag = %d\\n\\n", "C:\\\\abc\\\\file", fileNames.c_str(), fileName.c_str(), fileSuffix.c_str(), flag);
    
    	flag = get_fileName_fileSuffix("file.txt", fileNames, fileName, fileSuffix, suffix);
    	printf("str = %s, fileNames = %s   fileName = %s   fileSuffix = %s   flag = %d\\n\\n", "file.txt", fileNames.c_str(), fileName.c_str(), fileSuffix.c_str(), flag);
    
    	flag = get_fileName_fileSuffix("file", fileNames, fileName, fileSuffix, suffix);
    	printf("str = %s, fileNames = %s   fileName = %s   fileSuffix = %s   flag = %d\\n\\n", "file", fileNames.c_str(), fileName.c_str(), fileSuffix.c_str(), flag);
    
    	fileNames = "";
    	fileName = "";
    	fileSuffix = "";
    	flag = get_fileName_fileSuffix("", fileNames, fileName, fileSuffix, suffix);
    	printf("str = %s, fileNames = %s   fileName = %s   fileSuffix = %s   flag = %d\\n\\n", "\\"\\"", fileNames.c_str(), fileName.c_str(), fileSuffix.c_str(), flag);
    
    	return 0;
    
    

    运行截图:
    这个是后缀带点(.txt)的测试

  2. 测试Linux路径:
    /abc/file.txt
    /abc/file
    file.txt
    file

    int main(void) 
    
    	std::string fileNames = "";
    	std::string fileName = "";
    	std::string fileSuffix = "";
    	bool suffix = false;
    	bool flag = false;
    
    	// /abc/file.txt
    	// /abc/file
    	// /file.txt
    	// file
    	//printf("---Linux---\\n");
    
    	flag = get_fileName_fileSuffix("/abc/file.txt", fileNames, fileName, fileSuffix, suffix);
    	printf("str = %s, fileNames = %s   fileName = %s   fileSuffix = %s   flag = %d\\n\\n", "/abc/file.txt", fileNames.c_str(), fileName.c_str(), fileSuffix.c_str(), flag);
    
    	flag = get_fileName_fileSuffix("/abc/file", fileNames, fileName, fileSuffix, suffix);
    	printf("str = %s, fileNames = %s   fileName = %s   fileSuffix = %s   flag = %d\\n\\n", "/abc/file", fileNames.c_str(), fileName.c_str(), fileSuffix.c_str(), flag);
    
    	flag = get_fileName_fileSuffix("file.txt", fileNames, fileName, fileSuffix, suffix);
    	printf("str = %s, fileNames = %s   fileName = %s   fileSuffix = %s   flag = %d\\n\\n", "/file.txt", fileNames.c_str(), fileName.c_str(), fileSuffix.c_str(), flag);
    
    	flag = get_fileName_fileSuffix("file", fileNames, fileName, fileSuffix, suffix);
    	printf("str = %s, fileNames = %s   fileName = %s   fileSuffix = %s   flag = %d\\n\\n", "/file", fileNames.c_str(), fileName.c_str(), fileSuffix.c_str(), flag);
    
    	return 0;
    
    

    运行截图:
    这个是后缀不带点(txt)的测试


二、返回值 后缀索引 版

第一个版本是两个星期前写好的,后续回来看后,觉得返回值好像不是太友好,于是乎更改了以下版本代码。
返回的是 后缀索引 。

处理过程不变!

需要包含头文件:
#include <stdio.h>
#include <string.h>
#include <string>

/******************************************************************************
 *
 * 功能:
 *		获得 (文件名.后缀) 和 (文件名) 和 (文件后缀),Windows和Linux通用!
 *
 * 参数:
 *		_filePaht:			C语言字符指针,文件路径字符串
 *		_fullFileName:		C++字符串引用,获得[(文件名.后缀) 或 (文件名)]返回
 *		_fileName:			C++字符串引用,获得(文件名.后缀)返回
 *		_fileSuffix:		C++字符串引用,获得(后缀)返回
 *		_dot:				true,后缀带点(.txt);false,后缀不带点(txt);默认值为true
 *
 * 返回值:
 *		有后缀返回"."的索引;没有后缀则返回-1
 *
 ******************************************************************************/
int get_fileName_fileSuffix(const char *_filePaht, std::string &_fullFileName, std::string &_fileName, std::string &_fileSuffix, bool _dot = true) 

	// 合法性检查
	if (!_filePaht) return -1;
	std::string str = _filePaht;
	if (str.empty()) return -1;

	// .txt    的情况
	if (str.at(0) == '.') return -1;
	// file.   的情况
	if (str.at(str.size() - 1) == '.') return -1;



	char c = '\\0';

	// 区分此函数是在Windows环境调用还是Linux环境调用
#if defined (_WIN64) || defined (WIN32) || defined (_WIN32)
	//printf("---Windows---\\n");
	c = '\\\\';
#else
	//printf("---Linux---\\n");
	c = '\\/';
#endif

	// 去除字符串中的路径,剩下文件名
	std::string filename = strrchr(_filePaht, c) == NULL ? "" : strrchr(_filePaht, c) + 1;
	if (filename == "") 
		/* 说明字符串是file.txt或者file形式 */
		filename = _filePaht;

	 else 
		/* 说名字符串是C:\\\\abc\\\\file.txt或者C:\\\\abc\\\\file形式 */
	

	// 找到 . 的位置
	size_t _size = filename.rfind(".");
	// 获得文件名,不包含后缀
	_fileName = filename.substr(0, _size);

	// 获得文件后缀
	std::string strsuffix = "";
	if (_size != -1) 	// 不等于-1说明有后缀 file.txt形式

		// true后缀带点,false后缀不带点
		if (_dot == true) 
			strsuffix = filename.substr(_size);     // 文件后缀 .txt

		 else 
			strsuffix = filename.substr(_size + 1);     // 文件后缀 txt
		
	
	// 后缀
	_fileSuffix = strsuffix;

	// 获得文件名.后缀(file.txt | file)
	_fullFileName = filename;

	return _size;

测试:

int main(void) 

	std::string str = "abc.jpg";
	//std::string str = ".abcjpg";
	//std::string str = "abcjpg.";
	std::string fullFilename, filename, fileSuffix;
	int r = get_fileName_fileSuffix(str.c_str(), fullFilename, filename, fileSuffix, true);
	printf("r = %d\\n", r);
	printf("fullFilename = %s   filename = %s   fileSuffix = %s\\n", fullFilename.c_str(), filename.c_str(), fileSuffix.c_str());


	return 0;

运行截图:


总结

本人在做项目时经常需要在一个路径中提取出文件名和文件路径,但是在项目中写的是零散的代码,所以在这里总结成一个函数,通过这个函数去获取就方便多了,而且windows和linux通用!(废了两个三个小时写代码、测试和写博客,值得!)

以上是关于C/C++ Windows和Linux通用的一个函数,从文件路径中 提取 (文件名) 和 (文件后缀)的主要内容,如果未能解决你的问题,请参考以下文章

C/C++ 中的跨平台 unicode:使用哪种编码?

C/C++ 中的跨平台通用文本处理

linux和windows下,C/C++的sleep函数

c_cpp C ++ Windows和Linux导出库宏定义

C/C++/Assembly 以编程方式检测超线程在 Windows、Mac 和 Linux 上是不是处于活动状态 [重复]

推断函子返回类型的通用方法?