C/C++ 判斷檔案是否存在

本篇記錄一下 C/C++ 在 Windows / Linux / MacOS 各平台判斷檔案是否存在的方法,
其中介紹順序以多平台適用的方法優先,其次是特定平台的方法。

判斷檔案是否存在大約分為下列幾種方法,

  • ifstream (C++)
  • FILE (C)
  • acess()
  • std::filesystem::exists() (C++17)
  • boost::filesystem::exists() (Boost)

基本上推薦用 stat 或 acess

假設現在目錄下有 dir 資料夾、text.txt 文字檔、a.out 二進制執行檔,來看看這些範例的結果吧!

fstream (C++)

這方法是用於來測試開啟是否為文字檔,因為如果有個檔案是二進制檔這邊會回傳失敗。

cpp-file-exists.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// g++ cpp-file-exists.cpp -o a.out
#include <iostream>
#include <fstream>

using namespace std;

bool fileExists(const std::string& path) {
bool ret = false;
fstream fin(path.c_str());
//fstream fin;
//fin.open(path.c_str());
if (fin.good()) {
ret = true;
}
/*if (fin) {
ret = true;
}*/
/*if (fin.is_open()) {
ret = true;
}*/
fin.close();
return ret;
}

int main() {
cout << fileExists("nothing") << endl;
cout << fileExists("dir") << endl;
cout << fileExists("a.out") << endl;
cout << fileExists("text.txt") << endl;
return 0;
}

輸出結果:
結果不太符合我的預期,等我有空再試試吧!

1
2
3
4
0
0
0
1

FILE (C)

這個方式在開啟文字檔或開啟二進制檔都能正確的回傳狀態。

cpp-file-exists2.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// g++ cpp-file-exists2.cpp -o a.out
#include <iostream>
#include <fstream>

using namespace std;

bool fileExists(const std::string& path) {
FILE *fp;
if (fp = fopen(path.c_str(), "r")) {
fclose(fp);
return true;
}
return false;
}

int main() {
cout << fileExists("nothing") << endl;
cout << fileExists("dir") << endl;
cout << fileExists("a.out") << endl;
cout << fileExists("text.txt") << endl;
return 0;
}

輸出結果:

1
2
3
4
0
1
1
1

acess()

在linux下使用 access 要 #inclue <unistd.h>
access()應該比fopen()判斷檔案是否存在來的快很多
函式原型:int _access(const char *path, int mode);,使用範例如下:

cpp-file-exists3.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// g++ cpp-file-exists3.cpp -o a.out
#include <iostream>
#if _WIN32
#include <io.h>
#define _access access
#else
#include <unistd.h>
#endif

using namespace std;

bool fileExists(const std::string& path) {
bool ret = false;
if((access(path.c_str(), F_OK)) != -1) {
ret = true;
}
return ret;
}

int main() {
cout << fileExists("nothing") << endl;
cout << fileExists("dir") << endl;
cout << fileExists("a.out") << endl;
cout << fileExists("text.txt") << endl;
return 0;
}

1
2
3
4
#define	R_OK	4		/* Test for read permission.  */
#define W_OK 2 /* Test for write permission. */
#define X_OK 1 /* Test for execute permission. */
#define F_OK 0 /* Test for existence. */

輸出結果:

1
2
3
4
0
1
1
1

stat()

cpp-file-exists4.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// g++ cpp-file-exists4.cpp -o a.out
#include <sys/stat.h>
#include <iostream>

using namespace std;

bool fileExists(const std::string& path) {
struct stat info;
if (stat(path.c_str(), &info) == 0) {
return true;
}
return false;
}

int main() {
cout << fileExists("nothing") << endl;
cout << fileExists("dir") << endl;
cout << fileExists("a.out") << endl;
cout << fileExists("text.txt") << endl;
return 0;
}

輸出結果:

1
2
3
4
0
1
1
1

std::filesystem::exists() (C++17)

cpp-file-exists5.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// g++ cpp-file-exists5.cpp -o a.out -std=c++11 -lstdc++fs
#include <iostream>
#include <experimental/filesystem>
//#include <filesystem> // C++ 17

using namespace std;
namespace fs = std::experimental::filesystem;

bool fileExists(const std::string& path) {
fs::path myfile(path.c_str());
if (fs::exists(myfile)) {
return true;
}
return false;
}

int main() {
cout << fileExists("nothing") << endl;
cout << fileExists("dir") << endl;
cout << fileExists("a.out") << endl;
cout << fileExists("text.txt") << endl;
return 0;
}

輸出結果:

1
2
3
4
0
1
1
1

boost::filesystem::exists() (Boost)

cpp-file-exists6.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// g++ cpp-file-exists6.cpp -o a.out -I /usr/include/boost -lboost_filesystem
#include <iostream>
#include <boost/filesystem.hpp>

using namespace std;
namespace fs = boost::filesystem;

bool fileExists(const std::string& path) {
fs::path myfile(path.c_str());
if (fs::exists(myfile)) {
return true;
}
return false;
}

int main() {
cout << fileExists("nothing") << endl;
cout << fileExists("dir") << endl;
cout << fileExists("a.out") << endl;
cout << fileExists("text.txt") << endl;
return 0;
}

輸出結果:
結果有問題,等我有空再試試吧!

1
Segmentation fault (core dumped)

參考
C++ 判断文件文件夹是否存在
https://blog.csdn.net/u014436243/article/details/77312739

其它相關文章推薦
C/C++ 新手入門教學懶人包
C/C++ 判斷資料夾是否存在
std::filesystem::copy 複製檔案的用法與範例
std::filesystem::create_directory 建立資料夾的用法與範例
std::filesystem::exists 判斷檔案是否存在的用法與範例