无论我从何处运行程序,如何打开文件?

问题描述 投票:0回答:2

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;
}
  1. 我有一个文件
    d:\path1\some_file.dat
    和一个目录
    d:\path2
    。然后我将上面的代码编译为名为
    D:\path1\myprogram.exe
    .
  2. 的程序
  3. 输入命令
    cd d:\path1
    myprogram
    
    程序会打印“成功!!”。
  4. 输入命令
    cd d:\path2
    ..\path1\myprogram
    
    程序将打印“无法打开文件
    some_file.dat
    。错误代码 = 2”。

我的问题是,无论我从哪里运行程序,如何成功打开文件。如果

fopen
无法做到这一点,是否有库可以做到这一点?

回复评论:

我知道

fopen
可以从绝对路径加载文件,但我想让我的程序可移植。

c gcc fopen
2个回答
1
投票

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
始终与您的程序位于同一文件夹中,则可以针对类似问题提供 other answers

当然,您还可以将命令行指定的路径与硬编码的文件名组合起来,为此,如果您需要坚持使用 C 语言,请查看

sprintf
函数,或者例如
std::ostringstream
如果您实际上可以按照标签建议使用 C++。


0
投票

假设该文件与可执行文件位于同一文件夹中。
您可以使用传递给程序的

argv[0]
– 这是可执行文件名称。
我展示了它的三种运行方式:两种通过控制台,一种通过 GUI 文件管理器。

#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
© www.soinside.com 2019 - 2024. All rights reserved.