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

news/2024/10/31 5:33:50/

程序员必备: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 <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 类也是一个不错的选择。无论哪种方法,都需要注意文件不存在、权限不足等出错的情况。


http://www.ppmy.cn/news/40676.html

相关文章

BSN季度版本2023年3月31日迭代更新

根据BSN发展联盟规划&#xff0c;区块链服务网络&#xff08;BSN&#xff09;于2023年3月31日进行季度版本的迭代更新&#xff0c;在对现有BSN产品功能、性能和服务体验进行优化的同时&#xff0c;还推出多个全新的业务、功能&#xff0c;本文中将按照BSN-DDC基础网络、BSN Spa…

基于Java+SpringBoot+vue的社区维修平台设计与实现【源码(完整源码请私聊)+论文+演示视频+包运行成功】

博主介绍&#xff1a;专注于Java技术领域和毕业项目实战 &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;&#x1f3fb; 不然下次找不到哟 Java项目精品实战案例&#xff08;300套&#xff09; 目录 一、效果演示 二、…

C++ 枚举(enum)数据结构相关知识

enum数据结构 枚举&#xff08;enumeration&#xff09;是C中的一种用户自定义数据类型&#xff0c;它允许为一组整数赋予有意义的名称。枚举类型的主要目的是提高代码的可读性和可维护性。 枚举类型用关键字enum定义。以下是一个简单的枚举类型示例&#xff1a; enum Color {…

磁盘调度算法习题

注意&#xff08;不论被访问的下一个磁道号是几&#xff0c;计算移动距离都是&#xff1a;大数减小数&#xff09; 一&#xff0e;磁盘共有200个柱面(0-199)&#xff0c;它刚刚从92号磁道移到98号随道完成读写&#xff0c;假设此时系统中等待访问磁盘盘的磁道序列为190&#xf…

Python 判断闰年、Python 平方根

Python 判断闰年 以下实例用于判断用户输入的年份是否为闰年&#xff1a; # -*- coding: UTF-8 -*-# Filename : test.py # author by : www.w3cschool.cnyear int(input("输入一个年份: ")) if (year % 4) 0:if (year % 100) 0:if (year % 400) 0:print("…

REVA首届世界巡回交流会——澳门站 亚太峰会!

近日金融相关媒体报道:REVA亚太峰会将定于2023年5月8日—5月10日在澳门举行为期三天的会议交流,本次峰会由REVA主办,这一次的亚太峰会是疫情放开后国内外互联网市场交流的良好契机,也加速推动着国家和地区间互联网的经济、技术交流与合作。此次首战澳门亚太峰会会议,将拉开Reva…

Python结合OpenAI的GPT-3 API做数据分析

本文使用了OpenAI的GPT-3 API来生成数据分析报告。GPT-3是一种基于深度学习的自然语言处理模型&#xff0c;可以生成高质量的自然语言文本。在本示例中&#xff0c;我使用GPT-3来分析给定的CSV文件中的数据&#xff0c;并生成相应的报告。 以下是完整的Python代码示例&#xf…

使用Comparator 对List<Map>格式不严格字段排序

public static void main( String[] args ){String col1 "time";String col2 "num";//双数据源的集合ArrayList<Map> lists produceData(col1, col2);//对双数据源集合惊醒排序 这里2个字段的灵活配置升序降序SortBy2Cols(lists,col1,OrderType.D…