【C/C++ 应用开发 检测文件 】详解 C/C++ 中常用的 5 种文件存在检查方式

简介: 【C/C++ 应用开发 检测文件 】详解 C/C++ 中常用的 5 种文件存在检查方式

引言

在编写 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 <stdio.h>
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平台,你可能需要包含<sys/types.h>头文件并使用_stat替换stat。
#include <sys/stat.h>
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 <fstream>
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 <filesystem>
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 <QFile>
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 类也是一个不错的选择。无论哪种方法,都需要注意文件不存在、权限不足等出错的情况。

结语

在我们的编程学习之旅中,理解是我们迈向更高层次的重要一步。然而,掌握新技能、新理念,始终需要时间和坚持。从心理学的角度看,学习往往伴随着不断的试错和调整,这就像是我们的大脑在逐渐优化其解决问题的“算法”。

这就是为什么当我们遇到错误,我们应该将其视为学习和进步的机会,而不仅仅是困扰。通过理解和解决这些问题,我们不仅可以修复当前的代码,更可以提升我们的编程能力,防止在未来的项目中犯相同的错误。

我鼓励大家积极参与进来,不断提升自己的编程技术。无论你是初学者还是有经验的开发者,我希望我的博客能对你的学习之路有所帮助。如果你觉得这篇文章有用,不妨点击收藏,或者留下你的评论分享你的见解和经验,也欢迎你对我博客的内容提出建议和问题。每一次的点赞、评论、分享和关注都是对我的最大支持,也是对我持续分享和创作的动力。

目录
相关文章
|
6月前
|
存储 分布式数据库 API
技术好文:VisualC++查看文件被哪个进程占用
技术好文:VisualC++查看文件被哪个进程占用
|
2月前
|
Linux C++
Linux c/c++文件的基本操作
在Linux环境下使用C/C++进行文件的基本操作,包括文件的创建、写入、读取、关闭以及文件描述符的定位。
29 0
Linux c/c++文件的基本操作
|
3月前
|
C++ 内存技术
[转]Visual C++内嵌swf文件并播放
[转]Visual C++内嵌swf文件并播放
|
2月前
|
Linux C++
Linux c/c++文件虚拟内存映射
这篇文章介绍了在Linux环境下,如何使用虚拟内存映射技术来提高文件读写的速度,并通过C/C++代码示例展示了文件映射的整个流程。
67 0
|
2月前
|
Linux C++
Linux c/c++文件移动
这篇文章介绍了在Linux环境下,使用C/C++语言通过命令方式和文件操作方式实现文件移动的方法。
93 0
|
3月前
|
Linux API C++
超级好用的C++实用库之文件目录操作
超级好用的C++实用库之文件目录操作
49 0
|
3月前
|
JavaScript 前端开发 测试技术
一个google Test文件C++语言案例
这篇文章我们来介绍一下真正的C++语言如何用GTest来实现单元测试。
28 0
|
4月前
|
存储 算法 C++
【C++】C++ QT实现Huffman编码器与解码器(源码+课程论文+文件)【独一无二】
【C++】C++ QT实现Huffman编码器与解码器(源码+课程论文+文件)【独一无二】
130 4
|
4月前
|
存储 数据挖掘 C语言
【C/C++】C/C++车辆交通违章管理系统(源码+数据文件)【独一无二】
【C/C++】C/C++车辆交通违章管理系统(源码+数据文件)【独一无二】
|
4月前
|
监控 编译器 C++
【代码讲解】【C/C++】获取文件最后修改的时间(系统时间)
【代码讲解】【C/C++】获取文件最后修改的时间(系统时间)
159 0