不再迷茫 && 详解 C/C++ 中常用的 5 种文件存在检查方式

程序员必备:C/C++ 中检查文件是否存在的 4 种方法大比拼

  • 引言
  • fopen和fclose(C/C++)
    • fopen 函数原型
    • fclose 函数原型
    • 示例
  • 使用stat或_stat函数 (C/C++)
    • stat 函数原型
    • _stat 函数原型
    • 示例
  • 使用C++11及更高版本的std::ifstream
  • std::ifstream 类原型
    • std::ios_base::openmode 枚举类型
    • 示例
  • 使用C++17及更高版本的std::filesystem
    • std::filesystem::exists 函数原型
    • std::filesystem::path 类原型
    • std::filesystem::directory_entry 类原型
    • std::filesystem::directory_iterator 类原型
    • 示例
  • QFile
    • QFile 类原型
    • QIODevice::OpenMode 枚举类型:
    • 示例
  • 五种方式判断的对比
    • 使用fopen和fclose方法:
    • 使用stat或_stat函数:
    • 使用C++11及更高版本的std::ifstream:
    • 使用C++17及更高版本的std::filesystem
    • 使用 QFile 类
  • 总结

引言

在编写 C/C++ 程序时,我们经常需要检查文件是否存在。在这篇文章中,我们将介绍五种检查文件是否存在的方法。

  • 使用标准 C/C++ 中的 fopen 和 fclose 函数来检查文件是否存在。
  • 使用 stat 或 _stat 函数来检查文件是否存在。
  • 使用 C++11 及更高版本中的 std::ifstream 类来检查文件是否存在。
  • 使用 C++17 及更高版本中的 std::filesystem 库来检查文件是否存在。
  • 使用 Qt 中的 QFile 类来检查文件是否存在。

fopen和fclose(C/C++)

fopen 函数原型

FILE *fopen(const char *filename, const char *mode);

fopen 函数接受两个参数,分别是文件名和文件打开模式。它返回一个指向文件结构体的指针,如果打开文件失败则返回 NULL。

mode 参数是一个字符串,用于指定文件的打开模式。常见的文件打开模式包括:

“r”:以只读方式打开文件。
“w”:以写入方式打开文件(如果文件已存在,则会截断文件)。
“a”:以追加方式打开文件。
“r+”:以读写方式打开文件。
“w+”:以读写方式打开文件(如果文件已存在,则会截断文件)。
“a+”:以读写方式打开文件,并将写入的数据追加到文件末尾。
可能的出错方式包括:文件不存在、权限不足等。

fclose 函数原型

int fclose(FILE *stream);

fclose 函数接受一个指向已打开文件的指针,并关闭该文件。如果关闭文件成功,则返回 0;否则返回一个非零值。

可能的出错方式包括:文件不存在、文件已经关闭等。

示例

#include 

bool file_exists(const char *filename) {
    FILE *file = fopen(filename, "r");
    if (file != nullptr) {
        fclose(file);
        return true;
    }
    return false;
}

使用stat或_stat函数 (C/C++)

stat 函数原型

int stat(const char *pathname, struct stat *statbuf);

stat 函数接受两个参数,分别是文件名和一个指向 struct stat 结构体的指针。它返回一个整数值,表示函数调用的结果。

statbuf 参数用于存储文件的元数据,包括文件类型、权限、大小、时间戳等信息。它是一个 struct stat 类型的结构体,定义在sys/stat.h头文件中。

可能的出错方式包括:文件不存在、权限不足等。

_stat 函数原型

int _stat(const char *pathname, struct _stat *statbuf);

_stat 函数与 stat 函数功能相同,但它是 Microsoft Visual C++ 编译器所定义的,与 POSIX 标准略有不同。

statbuf 参数用于存储文件的元数据,包括文件类型、权限、大小、时间戳等信息。它是一个 struct _stat 类型的结构体,定义在 sys/stat.h 头文件中。

可能的出错方式包括:文件不存在、权限不足等。

总之,stat 或 _stat 函数可以用于获取文件的元数据,包括文件类型、权限、大小、时间戳等信息。在使用这些函数时,你需要注意出错的情况,例如文件不存在或权限不足等。

示例

//对于Windows平台,你可能需要包含头文件并使用_stat替换stat。
#include 

bool file_exists(const char *filename) {
    struct stat buffer;
    return (stat(filename, &buffer) == 0);
}

使用C++11及更高版本的std::ifstream

std::ifstream 类原型

class ifstream : public istream
{
public:
    explicit ifstream(const char* filename, ios_base::openmode mode = ios_base::in);
    explicit ifstream(const string& filename, ios_base::openmode mode = ios_base::in);
    ifstream(const ifstream&) = delete;
    ifstream& operator=(const ifstream&) = delete;
    ~ifstream();

    void open(const char* filename, ios_base::openmode mode = ios_base::in);
    void open(const string& filename, ios_base::openmode mode = ios_base::in);
    void close();

    bool is_open() const;
};

std::ifstream 类是 C++ 标准库中的一个流类,用于读取文件中的数据。它提供了多个构造函数和成员函数,用于打开、读取和关闭文件。

可能的出错方式包括:文件不存在、权限不足等。

std::ios_base::openmode 枚举类型

std::ios_base::openmode 枚举类型用于指定文件打开的模式,它定义在 头文件中。常见的文件打开模式包括:

ios_base::in:以只读方式打开文件。
ios_base::out:以写入方式打开文件(如果文件已存在,则会截断文件)。
ios_base::app:以追加方式打开文件。
ios_base::binary:以二进制模式打开文件(即不进行换行符的转换)。

示例

#include 

bool file_exists(const std::string &filename) {
    std::ifstream file(filename.c_str());
    return file.good();
}

使用C++17及更高版本的std::filesystem

std::filesystem::exists 函数原型

bool exists(const std::filesystem::path& p);

std::filesystem::exists 函数接受一个 std::filesystem::path 类型的参数,表示要检查的文件路径。它返回一个布尔值,表示该文件是否存在。

可能的出错方式包括:文件不存在、权限不足等。

std::filesystem::path 类原型

class path;

std::filesystem::path 类是 C++17 中新增的一个类,用于表示文件路径。它提供了多个成员函数,用于操作和查询文件路径,例如获取文件名、扩展名、父目录等。

可能的出错方式包括:路径不存在、权限不足等。

std::filesystem::directory_entry 类原型

class directory_entry;

std::filesystem::directory_entry 类表示文件系统中的一个目录项。它提供了多个成员函数,用于查询和操作该目录项。

可能的出错方式包括:目录项不存在、权限不足等。

std::filesystem::directory_iterator 类原型

class directory_iterator;

std::filesystem::directory_iterator 类表示一个目录中的文件迭代器。它提供了多个成员函数,用于遍历目录中的文件和子目录。

可能的出错方式包括:目录不存在、权限不足等。

示例

#include 

bool file_exists(const std::string &filename) {
    return std::filesystem::exists(filename);
}

QFile

QFile 类原型

class QFile : public QIODevice
{
public:
    explicit QFile(QObject *parent = nullptr);
    explicit QFile(const QString &name, QObject *parent = nullptr);
    ~QFile();

    bool open(OpenMode mode);
    bool open(FILE *fh, OpenMode mode, FileHandleFlags handleFlags = DontCloseHandle);
    bool open(int fd, OpenMode mode, FileHandleFlags handleFlags = DontCloseHandle);
    void close();

    bool exists() const;
};

QFile 类是 Qt 框架中的一个文件类,用于读写文件。它提供了多个构造函数和成员函数,用于打开、读取和关闭文件。

可能的出错方式包括:文件不存在、权限不足等。

QIODevice::OpenMode 枚举类型:

QIODevice::OpenMode 枚举类型用于指定文件打开的模式,它定义在 QIODevice 类中。常见的文件打开模式包括:

QIODevice::ReadOnly:以只读方式打开文件。
QIODevice::WriteOnly:以写入方式打开文件(如果文件已存在,则会截断文件)。
QIODevice::Append:以追加方式打开文件。
QIODevice::Text:以文本模式打开文件(即进行换行符的转换)。
总之,QFile 类是 Qt 框架中的一个文件类,用于读写文件。在使用这个类时,你需要注意出错的情况,例如文件不存在或权限不足等。

示例

#include 

bool file_exists(const QString& filename) {
    return QFile::exists(filename);
}

五种方式判断的对比

使用fopen和fclose方法:

  • 优点:

适用于C和C++,兼容性较好。
代码简单,易于理解。

  • 缺点:

实际打开文件进行读取,可能导致性能问题,特别是在高并发场景下。
在某些平台或文件系统上可能存在权限问题。
不支持Unicode路径(Windows平台)。
适用场景:适用于低并发、不需要Unicode支持的简单场景。

使用stat或_stat函数:

  • 优点:

适用于C和C++,兼容性较好。
不会打开文件,性能相对较好。

  • 缺点:

可能需要处理平台相关的问题(例如,在Windows上使用_stat)。
不支持Unicode路径(Windows平台)。
适用场景:适用于对性能敏感的场景,但要注意平台相关的问题。

使用C++11及更高版本的std::ifstream:

  • 优点:

适用于C++11及以上版本,利用现代C++特性。
不会实际读取文件,性能较好。

  • 缺点:

仅适用于C++,不适用于C语言项目。
依赖C++标准库,可能对依赖关系有影响。
适用场景:适用于现代C++项目,对性能有一定要求。

使用C++17及更高版本的std::filesystem

  • 优点:

适用于C++17及以上版本,充分利用现代C++特性。
代码简洁,易于理解。
性能较好,不会实际读取文件。
支持Unicode路径(Windows平台)。

  • 缺点:

仅适用于C++17及以上版本,不适用于旧版本C++或C语言项目。
适用场景:适用于现代C++项目,要求兼容Unicode路径和对性能有要求的场景。

使用 QFile 类

  • 优点

适用于 Qt 框架,易于与 Qt 项目集成。
代码简洁,易于理解。
性能较好,不会实际读取文件。
支持 Unicode 路径(跨平台)。
提供了更多的文件操作函数和成员函数,例如读写文件、复制、重命名等。

  • 缺点

仅适用于 Qt 项目,不适用于非 Qt 项目。
依赖于 Qt 框架。
适用场景:适用于 Qt 项目,要求跨平台和兼容 Unicode 路径的场景。


总结

选择适合您项目和需求的方法。如果您的项目是现代 C++(C++17 或更高版本),建议使用 std::filesystem 方法。如果需要兼容旧版本 C++ 或 C 语言项目,使用 stat 或 _stat 方法。如果只需要一个简单的解决方案,可以考虑使用 fopen 和 fclose 方法。不过,如果您的项目使用了 Qt 框架,那么使用 QFile 类也是一个不错的选择。无论哪种方法,都需要注意文件不存在、权限不足等出错的情况。

你可能感兴趣的:(C/C++,编程世界:,探索C/C++的奥妙,Qt应用开发,-,探索Qt的魅力与实践,c++,c语言,开发语言,linux,qt)