我正在制作一个C程序,需要读取GNU/Linux中的各种文件。
想象一下以下文件结构。
root
|- dir1
| |- file1.txt
|
|- dir2
|- file2.txt
现在想象一下我已经获得了
root/dir1/file1.txt
的相对路径并且我阅读了以下内容:
Load: ../dir2/file2.txt
...
我可以将
../dir2/file2.txt
字符串存储在 C 缓冲区中,但我不能直接将它与 fopen(3)
之类的东西一起使用,因为它会尝试打开相对于启动可执行文件的目录的路径。
使用 C 的
#include
时也会发生这种行为。该路径是相对于指定它的源的路径,而不是相对于启动编译器的路径。
我的问题是,如何打开
file2.txt
并了解 file1.txt
的(相对)路径以及存储在其中的相对路径?我想过获取 file1.txt
(root/dir1/
) 的目录并连接从那里获得的相对路径 (root/dir1/../dir2/file2.txt
),但也许有更好的方法。
如何打开
并了解file2.txt
的(相对)路径以及其中存储的相对路径?我想过获取file1.txt
(file1.txt
)的目录并连接从那里获得的相对路径(root/dir1/
),但也许有更好的方法。root/dir1/../dir2/file2.txt
C 没有用于路径操作的标准库函数。 不过,POSIX 定义了一些,所以如果您可以假设一个 POSIX 环境(并且您已经标记了 Linux,它足够接近),那么您可能会发现
dirname()
、basename()
和 realpath()
对你有一些用处,尽管这些并不能直接解决你的问题。
您描述的方法对于格式正确的输入应该可以正常工作,还包括到
file1.txt
的已知路径是否是绝对的。 我认为没有更简单的方法。 但是,在应用该方法之前,您可能确实想验证 file2.txt
的路径实际上是相对的。 您可能还需要考虑验证第二条路径的 ..
组件不会尝试导航到第一条路径的第一个组件之外。如果您可以依赖 POSIX,那么 另一种选择 :
#include <libgen.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
// ...
char *file1_copy = strdup(path_to_file1); // DO free() this
char *file1_dirname = dirname(file1_copy); // DO NOT free() this
// O_DIRECTORY and O_PATH are optional and Linux-specific
int dir1fd = open(file1_dirname, O_RDONLY | O_DIRECTORY | O_PATH);
// ... verify success ...
free(file1_copy);
int file2fd = openat(dir1fd, path_to_file2, O_RDONLY); // Possibly different flags
// ... verify success ...
// And maybe you want that as a stream, in which case:
FILE *file2 = openfd(file2fd, "r");
// ... verify success ...
请注意,无论给定的
file2.txt
路径是相对路径还是绝对路径,此方法都有效。 我并不是说它在任何绝对意义上都更好,但它可能对您有优势或者符合您的喜好。