讲师中心 微信公众号
AI工具推荐 视频效率加速

c++如何处理读取文件过程中的权限拒绝异常_std::error_code捕获【详解】

梦枫大大_9349

梦枫大大_9349

发布时间:2026-03-24 16:07:13

|

283人浏览过

|

来源于php中文网

原创

C++中无法通过std::ifstream获取系统级错误码,必须使用std::filesystem函数带std::error_code&参数的重载版本(如status(path, ec))或直接调用系统API(open/CreateFileW)才能捕获EACCES等真实错误。

c++如何处理读取文件过程中的权限拒绝异常_std::error_code捕获【详解】

std::filesystem::open_file 失败时拿不到 std::error_code?

不是 std::filesystem::open_file —— C++ 标准库压根没有这个函数。你真正调用的,大概率是 std::ifstream 构造或 open(),它底层失败时不会抛出带 std::error_code 的异常,而是设 failbit 或直接抛 std::ios_base::failure(需提前开启异常掩码)。

想拿到系统级错误码(比如 EACCES),必须绕过流封装,用 std::filesystem::status() 或直接调 open()(POSIX)/ CreateFileW(Windows)。

  • 用 std::ifstream 时,is_open() 返回 false 或 !ifs 为真,但无法区分“文件不存在”和“权限拒绝”
  • 开启异常:在构造后立刻调 ifs.exceptions(std::ios_base::failbit | std::ios_base::badbit),但抛出的是 std::ios_base::failure,其 .code() 默认是 std::errc::success,不反映真实 errno
  • 真正能拿到 std::error_code 的路径:先用 std::filesystem::status(path, ec) 检查权限,或用 std::filesystem::can_write(path)、std::filesystem::exists(path) 辅助判断

捕获 EACCES 必须用 std::error_code 参数重载

std::filesystem 的多数函数都提供两套接口:抛异常版(无 ec 参数)和填错码版(带 std::error_code& ec)。只有后者才能拿到原始系统错误,比如 EACCES。

例如读取前验证可访问性:

立即学习“C++免费学习笔记(深入)”;

C++14
C++14

C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。

下载
std::error_code ec;
auto s = std::filesystem::status("/etc/shadow", ec);
if (ec) {
    if (ec.value() == static_cast<int>(std::errc::permission_denied)) {
        // 真实权限拒绝
    }
}
  • 别写 if (ec) 就完事 —— ec 非空只代表出错,具体值要查 ec.value() 并映射到 std::errc
  • Windows 下 std::errc::permission_denied 对应 ERROR_ACCESS_DENIED,但 std::filesystem::status() 在多数实现中会做合理转换
  • 注意:std::filesystem::status() 本身也可能因权限问题失败(比如目录不可执行),此时 ec 是 std::errc::permission_denied,但不代表目标文件一定不可读 —— 它只是无法获取元信息

std::ifstream + errno 是最直接的 fallback 方案

当 std::filesystem 不可用(比如旧编译器)或你需要精确控制 open 行为时,直接调系统 API 最可靠。C++17 起可安全依赖 errno 值(线程局部),只要你在系统调用后立刻检查。

POSIX 示例:

#include <fcntl.h>
#include <cerrno>
int fd = open("/root/file.txt", O_RDONLY);
if (fd == -1) {
    if (errno == EACCES) {
        // 权限拒绝
    }
}
  • 不要在中间插入任何可能改写 errno 的调用(如 printf、std::cout)
  • std::ifstream 构造失败后,errno 不保证有效 —— 流内部可能已覆盖它,所以不能依赖 errno 解释流错误
  • Windows 下用 CreateFileW,失败时调 GetLastError(),对应 ERROR_ACCESS_DENIED;别用 _doserrno,它不可靠

std::error_code 和 std::errc::xxx 的类型匹配陷阱

std::error_code 的 value() 是 int,但 std::errc 枚举值不是裸 int —— 直接比较 ec.value() == std::errc::permission_denied 可能失败(隐式转换问题)。

  • 正确写法:ec == std::errc::permission_denied(std::error_code 重载了 ==)
  • 错误写法:ec.value() == static_cast<int>(std::errc::permission_denied)</int> —— 在某些标准库实现中,std::errc 值可能被包装成其他域(domain),导致数值不等
  • 更安全的判断:ec.category() == std::system_category() && ec.value() == EACCES(POSIX)或 ec.value() == ERROR_ACCESS_DENIED(Windows),但失去跨平台性

权限异常不是“有没有错”的问题,而是“错得够不够细”的问题。漏掉 ec 参数、混淆 value() 和枚举比较、在流操作后查 errno —— 这三处一踩,就只能打印“打开失败”,再没法告诉用户到底是路径错了,还是 sudo 忘了。

相关文章

c++速学教程(入门到精通)
c++速学教程(入门到精通)

c++怎么学习?c++怎么入门?c++在哪学?c++怎么学才快?不用担心,这里为大家提供了c++速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

c++

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

咔片AIPPT

一款在线AI演示文稿制作工具,可根据主题和内容需求辅助生成PPT结构与页面,提高演示材料制作效率。

立刻MV
立刻MV Hot

立刻MV是一款AI文本写作工具,AI 音乐视频(MV)创作工具。

Laper
Laper Hot

Laper是专为编剧、导演和制片人推出的 AI 原生剧本创作工具。

PixTV
PixTV Hot

PixTV是一款面向AIGC内容创作的AI视频生成工具。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

VibeKnow
VibeKnow Hot

一款AI视频创作工具,主要用于全球首个AI知识视频创作平台,文档、文章、网页,一键生成视频,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

火山引擎

火山引擎是一款面向企业的云计算与AI服务平台。

相关专题

更多
printf用法大全
printf用法大全

php中文网为大家提供printf用法大全,以及其他printf函数的相关文章、相关下载资源以及各种相关课程,供大家免费下载体验。

808

2023.06.20

fprintf和printf的区别
fprintf和printf的区别

fprintf和printf的区别在于输出的目标不同,printf输出到标准输出流,而fprintf输出到指定的文件流。根据需要选择合适的函数来进行输出操作。更多关于fprintf和printf的相关文章详情请看本专题下面的文章。php中文网欢迎大家前来学习。

1029

2023.11.28

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

6599

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

3205

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

4128

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

2825

2025.08.29

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

3168

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

5009

2025.10.17

Gradle插件开发入门教程
Gradle插件开发入门教程

本专题介绍Gradle插件开发的基本流程,涵盖插件类编写、自定义任务注册、扩展参数设计和插件应用方法,帮助你理解插件如何组织构建逻辑,减少多个项目之间的重复配置。

20

2026.10.22

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++ Core Guidelines
C++ Core Guidelines

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

C++ 官方标准说明
C++ 官方标准说明

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn