提问人: 提问时间:11/3/2023 更新时间:11/6/2023 访问量:121
无论我从哪里运行我的程序,如何打开文件?
How to open a file no matter where I run my program from?
问:
fopen
始终尝试从工作路径加载文件。为了重现这个错误,我在下面编写了一个演示代码:
#include<stdio.h>
int main(void) {
FILE* my_file = NULL;
const char* file_name = "some_file.dat";
errno_t errcode = fopen_s(&my_file, file_name, "rb");
if (errcode != 0) {
printf("Cannot open the file `%s`. Error code = %d", file_name, errcode);
}
else {
puts("Success!!");
}
return errcode;
}
- 我有一个文件和一个目录。然后,我将上面的代码编译为名为 .
d:\path1\some_file.dat
d:\path2
D:\path1\myprogram.exe
- 输入命令,程序将打印“成功!!”。
cd d:\path1 myprogram
- 输入命令,程序将打印“无法打开文件。错误代码 = 2”。
cd d:\path2 ..\path1\myprogram
some_file.dat
我的问题是,无论我从哪里运行我的程序,如何成功打开文件。如果不能做到这一点,有没有一个图书馆可以做到这一点?fopen
回复评论:
我知道可以从绝对路径加载文件,但我想让我的程序可移植。 并且始终在同一条路径上。fopen
myprogram.exe
some_file.dat
答:
fopen
可以采用文件的完整绝对路径,或者,如果它得到一个不完整的路径,它必须假定该路径是相对的;相对路径始终相对于当前工作目录。
简而言之,就像任何其他打开文件的工具一样,无法神奇地猜出您的意思;它需要确切地知道它应该在哪里查找文件。fopen
您可以指定如下所示的完整路径:
// ....
const char* file_name = "D:\\path1\\some_file.dat";
// ....
但是,从您的评论来看,您的问题似乎是您在编译时不知道文件的确切完整路径;因此,您可能希望以某种方式从程序用户那里获取文件的路径;
执行此操作的一种典型方法是从命令行的参数中读取它:
#include<stdio.h>
int main(int argc, char** argv) {
FILE* my_file = NULL;
if (argc < 2) {
puts("You need to specify a filename!");
return 2;
}
errno_t errcode = fopen_s(&my_file, argv[1], "rb");
if (errcode != 0) {
printf("Cannot open the file `%s`. Error code = %d", argv[1], errcode);
}
else {
puts("Success!!");
}
return errcode;
}
运行:
测试用例 1:
> cd d:\path1
> myprogram some_file.dat
Success!!
测试用例 2(相对):
> cd d:\path2
> ..\path1\myprogram ..\path1\some_file.dat
Success!!
测试用例 2(绝对):
> cd d:\path2
> ..\path1\myprogram d:\path1\some_file.dat
Success!!
如果您始终与程序位于同一文件夹中,则对于类似问题还有其他答案。some_file.dat
当然,您也可以将命令行中指定的路径与硬编码文件名相结合,为此,如果您需要坚持使用 C 语言,请查看函数,或者例如 如果您实际上可以按照标签的建议使用 C++。sprintf
std::ostringstream
假设文件与可执行文件位于同一文件夹中。
您可以使用传递给程序的 – 这是可执行文件名称。
我已经展示了它以三种方式运行:两种来自控制台,一种来自 GUI 文件管理器。argv[0]
#include <stdio.h>
#include <string.h>
#define SLASH_CHAR '\\' // Windows
//#define SLASH_CHAR '/' // Linux
int main(int argc, char *argv[]) {
const char* file_name = "some_file.dat"; // desired filename
printf("argv[0] = %s\n", argv[0]); // the executable
// allocate enough memory to create a file name
char *fname = malloc(strlen(argv[0]) + strlen(file_name) + 1);
if(fname == NULL)
return 1;
// find the last path separator in the executable (if any)
char *slash_ptr = strrchr(argv[0], SLASH_CHAR);
if (slash_ptr == NULL) {
// just use the file name
strcpy(fname, file_name);
}
else {
// create a new file name
strcpy(fname, argv[0]);
size_t slash_ind = slash_ptr - argv[0];
strcpy(fname + slash_ind + 1, file_name);
}
printf("fname = %s\n", fname);
free(fname);
getchar();
return 0;
}
从控制台当前目录运行
argv[0] = test
fname = some_file.dat
在控制台中从并行文件夹运行
argv[0] = ..\temp\test
fname = ..\temp\some_file.dat
从 Windows 文件管理器运行
argv[0] = F:\TEMP\test.exe
fname = F:\TEMP\some_file.dat
评论
argv[0]
some_file.dat
const char* file_name = "some_file.dat";
const char *file_name = "d:\\path1\\some_file.dat";