编程学习工具篇--boost

前言

        从18年就开始接触boost,但是从来没有细细了解过它的功能,因工作需求,这几天看了下boost,发现确实很强大,真心为以前的无知感到羞愧,boost包含的内容太多,数据结构,算法,计时等,如果没有具体的使用需求,很难掌握,所以,先从简单常用的东西开始。
       学习boost的核心价值是为了更好的使用C/C++,将其作为C/C++的标准扩展,如果遇到重复性的功能且运行模块是相对独立的,会尽可能选择功能较大的一方作为该功能的落脚点。
       win下编译完全功能版的boost大约1G左右,在实际使用时,如果嫌弃它过大,可以进行一定程度的阉割,具体实现方法可以百度下。

一、Filesystem简介

       作为boost开篇,把filesystem模块的使用记录下,因为该模块的主要功能是处理fileDirectories,拟补了C/C++的空缺,也解决了跨平台的壁垒,同时,也是考虑使用相对广泛且该模块相对独立,所以,先入手该模块。

二、功能学习

       文件及文件夹的操作,相对来说比较固定,新建、删除、复制,重命名,很符合win下文件管理器的操作指南,但是这其中存在的很多逻辑判断是比较费心劳神的,下面就针对这几种功能的应用场景做一些记录学习。

2.1新建文件夹

       在创建文件/夹时,需要一个路径记录文件/夹的位置,因此,在filesystem中引入了变量boost::filesystem::path的概念,其实path在一定程度上是可以和string表示路径互换的,只是,path作用比较单一,只表示路径或者某一个路径下的文件,不容易引起误解。
       首先,需要给定一个path,当然,这个path可以是文件夹,可以是文件,也可以是一些莫名其妙的东西:

path p("./") //当前文件夹

       是不是和std::string有点类似,在接下来的操作中,就以p作为示例。
       在文件管理器(win)中新建一个文件夹的操作很简单,只需要用户一步一步进入目标文件夹,然后右键新建即可,但是用代码,就需要留心了,毕竟人非圣贤,孰能无过,谁又知道你给的参数是否正确,比如,这个p,只是一个字符串,程序很难知道它具体表示的是什么意思,如果出现非法操作,很有可能导致程序直接崩溃,所以,在拿到p后首先需要对其进行判别,判断是否存在,判断他的属性等:

if (exists(p)) {
	if (is_regular_file(p))
		LOG(INFO) << p << "size is " << file_size(p);
	else if (is_directory(p)) 
		LOG(INFO) << p << "is a directory , size is ";
	else
		LOG(WARNING) << "don't know";
}
else {
	LOG(INFO) << p << " do not exist";
	create_directory(p);
}

       上述只是一个简单的操作说明,重点在于逻辑的判断,通过多个if(只是不习惯用switch)的设定以及这几句代码,可以实现一些小功能,但是牵扯到应用场景的不同,会出现不同的组合方式,会在下面介绍。
       新建文件夹,主要有两个命令:

boost::filesystem::create_directories(path p);
boost::filesystem::create_directory(path p);

       两个命令的主要区别是:create_directories()可以多层创建,简单来说,若p = "./123/456",如果不存在123,则该指令可以先创建文件夹123然后再创建文件夹456,但是,若用create_directory()命令,在没有123的前提下创建456,程序直接崩溃。

2.2 删除文件(夹)

       删除文件(夹)也有两条命令:

remove(path p)
remove_all(path p)

        主要区别:remove()只能用来删除一个文件或者文件夹,当提供的文件夹里面还存在其余文件时,该命令可导致程序崩溃。

2.3 重命名与复制

       相对来说简单很多,一共3条命令:

rename(old, new);
copy_file(old, new);
copy_directory(old, new);

       在这里,有几点需要注意:

  • 需要注意重名问题,在renamecopy时,若新名字有重名,程序直接挂掉,这与win下操作逻辑一样。
  • copy_file只能复制文件,用来复制文件夹直接挂掉
  • copy_directory()只能复制文件夹,但是,不负责复制文件夹中的内容。

三、应用场景

       场景1:在进行数据处理时,需要保存下中间过程的变量,而且还要方便查阅;
       解决思路:基于系统时间创建一些列的文件夹,并将相应数据保存至对应时刻的文件夹中。以年月日作为一级目录,以时分秒作为二级目录,并将数据存储其中。

std::string path_f = "./";
std::string path_s = "";
boost::posix_time::ptime now_data = second_clock::local_time();
auto now_time = now_data.time_of_day();
//git current time as folder names
path_f = path_f + to_string(now_data.date().year()) + “-” 
					   + to_string(now_data .date().month()) + "-" 
					   + to_string(now_data .date().day());
path_s =  to_string(now_time.hours()) + “-” +
			    to_string(now_time.minutes()) + "-" +
			    to_string(now_time.seconds);
path p = path_f + "/" + path_s;
//create directories
create_directories(p);

       上述是通过create_directories()创建的,缺点就是,太智能了,不管有没有目标文件夹都会自己创建,过程不好控制,如果想使用create_directory()创建文件夹,可参考本文第一个示例即可。

       场景2:在创建文件夹时,希望按照0,1,2,3...顺序命名的方式进行;
       解决思路:先遍历目标文件夹内部文件的数量,然后进行+1操作;同时,也可以根据自己的需求统计其中文件与文件夹的数量:

int count = 0;
for (auto it : directory_iterator(p))
		count ++;

       场景3:给定路径p,获取其内部包含的所有文件的名称;
       解决思路:一个递归搞定

bool get_files(path p, std::vector<path>& names)
{
	if (exists(p)) {
		if (is_directory(p)) {
			for (auto it : directory_iterator(p)) {
				if (is_regular_file(it))
					names.push_back(it);
				else if (is_directory(it))
					get_files(it, names);
			}
		} else 
			names.push_back(p);
	}
	else
		return false;
}
std::vector<path> names;
bool result = get_files(p, names);

猜你喜欢

转载自blog.csdn.net/weixin_42823098/article/details/115591080