上一节中,我们对路径进行了标准化输出。使用了filesystem::path
类,并且了解了如何获取路径,并进行检查,以及其他一些原理性的东西。也能帮助我们将字符串组成路径,从而对路径进行再次解析。
path
已经将操作系统的一些细节为我们进行了封装,不过我们还是需要了解一些细节。
本节我们也将了解到,如何将绝对路径和相对路径进行合并和分解。
本节中,我们将围绕着相对路径和绝对路径进行,从而了解path
类的有时,以及其对应的辅助函数。
-
包含必要的头文件,并声明所使用的命名空间:
#include <iostream> #include <filesystem> using namespace std; using namespace filesystem;
-
然后,我们实例化一个
path
对象。不过这次,路径中的文件是否存在就没有那么重要了。这里有些函数,在文件不存在的时候会抛出异常。int main() { path p {"testdir/foobar.txt"};
-
现在我们来了解一下不同的文件系统库函数。
current_path
将返回我们执行程序的路径,也就是工作目录。absolute
能接受一个相对地址,就像我们定义的p
一样。system_complete
在Linux,MacOS和类UNIX操作系统上与absolute
的功能相同。在Windows下我们将获取一个带有盘符(比如c:
)的绝对地址。canonical
与absolute
的功能相同,不过其删除了所有的.
和..
。我们可以使用如下的方式使用这些函数:cout << "current_path : " << current_path() << "\nabsolute_path : " << absolute(p) << "\nsystem_complete : " << system_complete(p) << "\ncanonical(p) : " << canonical(p) << '\n';
-
path
另一个优势在于,其对/
操作符进行了重载。通过这种方式我们可以连接文件夹和文件。让我们组合一个,然后进行打印:cout << path{"testdir"} / "foobar.txt" << '\n';
-
我们将
canonical
与合并的路径一起使用。通过给定canonical
一个相对地址,比如"foobar.txt"
,和一个合并的绝对地址current_path() / "testdir"
,其将会返回给我们一个绝对地址。在另一个调用中,我们给定我么的路径为p
(假设为"testdir/foobar.txt"
),并且通过current_path()
获取当前位置的绝对路径,我们这里就使用"testdir"
好了。其结果与current_path()
相同,因为间接获得了绝对地址。在这两次调用中,canonical
将会返回给我们相同的绝对地址:cout << "canonical testdir : " << canonical("foobar.txt", current_path() / "testdir") << "\ncanonical testdir 2 : " << canonical(p, current_path() / "testdir/..") << '\n';
-
我们也可以对两个非标准化的路径进行比较。
equivalence
能接受两个路径,并在内部将两个路径进行标准化,如果这两个路径相同,就会返回true,否则会返回false。这个例子中,相应的路径必须存在,否则就会抛出一个异常:cout << "equivalence: " << equivalent("testdir/foobar.txt", "testdir/../testdir/foobar.txt") << '\n'; }
-
编译并运行代码,将会得到如下的输出。
current_path()
会返回我笔记本上的HOME目录,因为我在这个路径下执行的程序。相对路径p
会通过absolute_path
,system_complete
和canonical
预先进行准备。我们能看到absolute_path
和system_complete
的结果都一样,因为我使用的是Mac系统。在使用Windows操作系统的机器上,system_complete
将会前置一个C:
,或者是工作路径的磁盘盘符:$ ./canonical_filepath current_path: "/Users/tfc" absolute_path : "/Users/tfc/testdir/foobar.txt" system_complete : "/Users/tfc/testdir/foobar.txt" canonical(p): "/Users/tfc/testdir/foobar.txt" "testdir/foobar.txt" canonical testdir : "/Users/tfc/testdir/foobar.txt" canonical testdir 2 : "/Users/tfc/testdir/foobar.txt" equivalence: 1
-
这个简单的程序中,就不对异常进行处理了。当从
testdir
文件夹中将foobar.txt
文件删除时,程序将因为抛出异常的原因而终止。canonical
函数需要路径真实存在。还有一个weakly_canonical
,但其不符合我们的要求。$ ./canonial_filepath current_path: "/Users/tfc" absolute_path : "/Users/tfc/testdir/foobar.txt" system_complete : "/Users/tfc/testdir/foobar.txt" terminate called after throwing an instance of 'std::filesystem::v1::__cxx11::filesystem_error' what():filesystem error: cannot canonicalize: No such file or directory [testdir/foobar.txt] [/Users/tfc]
本节的目的就是如何快速的组成新的路径。其主要还有通过path
类重载的/
操作符来完成。另外,文件系统函数的相对路径和绝对路径是一致的,并且路径中包含.
和..
。
很多函数会返回一个转换或未转换的path
实例。我们不会将所有函数都列在这里,如果想要了解它们,去看下C++手册是个不错的选择。
path
类中有很多的成员函数,很值得一看。让我们来了解一下,对于一个路径来说,成员函数返回的是哪一部分。下面的图就为我们描述了在Windows和UNIX/Linux下,对应函数所返回的路径:
这样我们就能很容易的了解到,path
的那个函数返回的是绝对地址。相对地址中,root_path
,root_name
和 root_directory
部分都空的。relative_path
将会返回一个相对地址。