C語言怎麼打開檔案?
C語言要打開一個檔案可以使用标準庫的fopen函數,來看下fopen函數的聲明:
FILE *fopen(const char *filename, const char *mode)
其中,filename參數的類型是字元串,用于指定要打開檔案的路徑,可以是絕對路徑,也可以是相對路徑。mode參數的類型也是字元串,用于指定打開檔案的操作模式,比如"r"(隻讀模式)等等。
那麼,這裡要讨論的是filename參數使用相對路徑的時候,相對位置到底是哪裡呢?
1、源代碼檔案所在路徑?
2、源代碼編譯後的可執行檔案所在路徑?
3、我們自己目前所在的路徑?
你覺得是哪裡?
答案是3,我們自己目前所在的路徑。Show me the code,寫個代碼證明一下。
證明fopen函數相對路徑的位置
建立個新目錄CFileTest,在目錄下面建立main.c源檔案,hello.txt文本檔案,以及build子目錄(存放編譯後的可執行檔案)。目錄結構如下:
CFileTest
- build
- hello.txt
- main.c
hello.txt隻是一個普通的文本檔案,裡面隻有Hello World字元串。
main.c源代碼的功能也很簡單,就是使用fopen函數打開相對路徑下的hello.txt文本檔案,并列印出檔案内的字元串:
#include <errno.h>
#include <stdio.h>
#include <string.h>
int main() {
FILE* pFile;
//以隻讀模式打開相對路徑下的hello.txt檔案
pFile = fopen("hello.txt", "r");
//如果檔案打開失敗,列印錯誤碼和錯誤描述
if (pFile == NULL) {
int errorCode = errno;
char* errorMsg = strerror(errorCode);
printf("Open file fail, errorCode:%d, errorMsg:%s\n", errorCode, errorMsg);
return -1;
}
//如果檔案打開成功,列印出檔案内容
int c;
while (1) {
c = fgetc(pFile);
if (feof(pFile)) {
printf("\n");
break;
}
printf("%c", c);
}
fclose(pFile);
return 0;
}
1、證明相對路徑不是相對于源檔案
現在進入build子目錄,在build子目錄下編譯main.c,并把可執行檔案指定到build目錄:
nan@HWin-Jianan:~/CFileTest$ cd build
nan@HWin-Jianan:~/CFileTest/build$ gcc ../main.c -o main
nan@HWin-Jianan:~/CFileTest/build$ ls -l
total 20
-rwxr-xr-x 1 nan nan 17016 Feb 4 00:14 main
可以看到在build子目錄下已經生成main可執行檔案,目前的目錄結構如下:
CFileTest
- build
- main
- hello.txt
- main.c
在build目錄執行下main可執行檔案:
nan@HWin-Jianan:~/CFileTest/build$ ./main
Open file fail, errorCode:2, errorMsg:No such file or directory
可以看到hello.txt檔案和main.c源檔案同在一個目錄,但結果卻報錯了,找不到hello.txt這個檔案。說明"hello.txt"這個相對路徑不是相對于源檔案的路徑。
2、證明相對路徑不是相對于可執行檔案所在路徑
把hello.txt檔案移動到build目錄下:
nan@HWin-Jianan:~/CFileTest/build$ mv ../hello.txt ./
目前目錄結構如下:
CFileTest
- build
- hello.txt
- main
- main.c
在build目錄下繼續執行main可執行檔案:
nan@HWin-Jianan:~/CFileTest/build$ ./main
Hello World!
可以看到成功列印出了hello.txt檔案内容"Hello World",這能确定相對路徑是相對于可執行檔案所在路徑了嗎?别急,别忘了我們自己目前所在路徑也在build目錄下,也有可能是因為相對于我們自己目前所在路徑才成功找到檔案的。那麼,切換下我們自己目前所在的路徑看看,切換到上一級CFileTest目錄再執行看看:
nan@HWin-Jianan:~/CFileTest/build$ cd ..
nan@HWin-Jianan:~/CFileTest$ ./build/main
Open file fail, errorCode:2, errorMsg:No such file or directory
又找不到檔案了,可以确定相對路徑也不是相對于可執行檔案所在的路徑。
說明:可執行檔案所在路徑不一定就是我們自己目前所在的路徑。比如上面這次實驗,可執行檔案在build目錄下,我們自己目前所在的路徑在CFileTest目錄下。
3、證明相對路徑相對于我們自己目前所在路徑
再次把hello.txt檔案移動到CFileTest目錄下:
nan@HWin-Jianan:~/CFileTest$ mv ./build/hello.txt ./
移動後目錄結果恢複為:
CFileTest
- build
- main
- hello.txt
- main.c
在CFileTest目錄下執行可執行檔案:
nan@HWin-Jianan:~/CFileTest$ ./build/main
Hello World!
成功找到hello.txt檔案,說明相對路徑是相對于我們自己目前所在路徑的。
就這?有更直接的證據嗎?那就gdb debug模式打個斷點,列印下執行檔案時目前的路徑。
首先重新gcc編譯下源檔案,增加-g參數保留下調試資訊:
nan@HWin-Jianan:~/CFileTest$ gcc -g main.c -o ./build/main
使用gdb調試main可執行檔案,在源代碼第8行"pFile = fopen("hello.txt", "r");"處打個斷點,然後運作程式到這個斷點:
nan@HWin-Jianan:~/CFileTest$ gdb ./build/main
GNU gdb (Ubuntu 9.2-0ubuntu1~20.04.1) 9.2
...
Reading symbols from ./build/main...
(gdb) b 8
Breakpoint 1 at 0x1235: file main.c, line 8.
(gdb) r
Starting program: /home/nan/CFileTest/build/main
Breakpoint 1, main () at main.c:8
8 pFile = fopen("hello.txt", "r");
輸入pwd指令,列印可執行檔案時目前路徑:
(gdb) pwd
Working directory /home/nan/CFileTest.
可以看到,檔案執行時的工作目錄在CFileTest,與我們自己目前所在的目錄一緻。
總結
C語言的fopen函數,如果指定相對路徑的檔案需要注意一下,相對路徑是相對于我們自己目前所在的路徑,而不是源檔案或者可執行檔案的路徑。