我正在使用 fopen("aaa\bbb\ccc\myfile.txt","w")
来创建输出文件。但是文件夹 aaa
、bbb
和 ccc
不存在。解决这个问题的最佳方法是什么?是否有任何标准方法可以要求 fopen()
创建所有需要的文件夹?
这里还有另一种用纯C编写的替代方案,不依赖于strtok
(该函数会破坏传递的文件路径字符串):
const char pathSeparator =
#ifdef _WIN32
'\\';
#else
'/';
#endif
// Given a file path, create all constituent directories if missing
void create_file_path_dirs(char *file_path) {
char *dir_path = (char *) malloc(strlen(file_path) + 1);
char *next_sep = strchr(file_path, pathSeparator);
while (next_sep != NULL) {
int dir_path_len = next_sep - file_path;
memcpy(dir_path, file_path, dir_path_len);
dir_path[dir_path_len] = '\0';
mkdir(dir_path, S_IRWXU|S_IRWXG|S_IROTH);
next_sep = strchr(next_sep + 1, pathSeparator);
}
free(dir_path);
}
fopen()
等函数,也不知道或关心你提供的路径中使用的/
或\
作为两个主要操作系统家族中的目录分隔符。strtok()
这样的函数可能不安全,您最好采用不同的方法将路径转换为要创建的目录列表。
您可能还需要处理目录已经存在的情况,或者文件存在于您想放置一个目录的路径上。
在C标准库中,打开和写入文件的函数可以在现有目录中创建新文件,但是无法创建新目录。为了解决这个问题,建议使用头文件"sys/stat.h"中的"mkdir"函数和头文件"unistd.h"中的"chdir"函数。
例如,如果编写要在Windows 10上的Cygwin中使用的C程序,可以使用以下方法:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <errno.h>
#include <error.h>
int main (void)
{
FILE * fp;
chdir("/cygdrive/d");
if (mkdir("aaa", S_IRWXU|S_IRWXG|S_IROTH))
{
error(EXIT_FAILURE, errno, "Failed to create directory aaa");
}
chdir("aaa");
if (mkdir("bbb", S_IRWXU|S_IRWXG|S_IROTH))
{
error(EXIT_FAILURE, errno, "Failed to create directory bbb");
}
chdir("bbb");
if (mkdir("ccc", S_IRWXU|S_IRWXG|S_IROTH))
{
error(EXIT_FAILURE, errno, "Failed to create directory ccc");
}
chdir("ccc");
fp=fopen("MyFile.txt", "w");
if (!fp)
{
error(EXIT_FAILURE, errno, "Failed to open file for writing");
}
fprintf(fp, "Test.\n");
fclose(fp);
return 0;
}
这将创建目录 "D:\aaa\bbb\ccc",然后在该目录中创建名为 "MyFile.txt" 的文件,最后向该文件写入 "Test.\n"。
可能不如其他的那么优雅,但是:
system("mkdir aaa\\bbb\\ccc\\");
FILE * fp;
fp = fopen("aaa/bbb/ccc/myfile.txt","w");
对于 Linux,请使用 -p
选项和斜杠。
如果您正在使用 Windows,则应在 system()
函数中使用反斜杠。
如果你的程序中可以混合一些 C++,那么 boost.filesystem 库有一个非常方便的 function 可以创建所有中间目录。
bool create_directories(const path& p);
fopen()
,那么您应该先创建父目录。system("mkdir -p aaa/bbb/ccc");
fopen("aaa/bbb/ccc/myfile.txt","w");
在这个程序中,不要忘记包含头文件<stdlib.h>
mkdir
命令可能不存在或不知道-p
选项。 - Basile Starynkevitchfopen() 用于打开文本或二进制文件的输入流,而不是目录文件。如果您想要在包含不存在目录的路径中打开文件,则建议使用 /sys/stat.h 头文件的 mkdir() 方法。一旦准备好目录,您就可以使用 fopen() 打开所需的文件(如果尚不存在,则创建它)。 这是我用来在 $HOME 文件夹的一个目录中创建文件的方法:
char* home_dir= getenv("HOME");
/*creates the directory with specified modes*/
mkdir(strcat(home_dir, "/make-a-note/"),S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
/*used the strcat() to generate the file-path.*/
personal_work=fopen(strcat(home_dir,"personal_work.txt"),"a+");
strcat()
调用是恶意的:它肯定会越界覆盖环境变量内容的缓冲区。这种未定义行为很可能会损坏某些其他环境变量,甚至更糟。 - cmaster - reinstate monica
fopen
永远不会创建目录。已经有一个关于扩展的mkdir()
可以创建多级目录的问题,并且有很好的答案,这与你想要的类似。你需要对"aaa/bbb/ccc/"
进行多级 mkdir,然后调用fopen
。 - user2404501fopen()
函数不支持创建目录,但如果目录存在,这将是必要的。 - unwind