导读:本期聚焦于小伙伴创作的《C++如何处理移动硬盘拔出导致的文件写入异常IO异常捕获》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《C++如何处理移动硬盘拔出导致的文件写入异常IO异常捕获》有用,将其分享出去将是对创作者最好的鼓励。

在C++开发场景中,将文件写入移动硬盘时,用户突然拔出设备会直接导致写入操作中断,触发底层IO错误。这类错误不属于常规的逻辑错误,往往会导致程序抛出未捕获的异常进而崩溃,需要针对性设计捕获和处理逻辑。

C++如何处理移动硬盘拔出导致的文件写入异常IO异常捕获

C++文件写入的常见IO异常类型

移动硬盘拔出触发的异常属于底层输入输出错误,不同C++标准库组件的表现不同:使用C标准库的stdio函数时,错误会反映在返回值中;使用C++标准库的fstream时,会设置流的状态位,若开启异常开关还会抛出std::ios_base::failure类型的异常。

fstream流状态位说明

  • badbit:表示发生致命的底层错误,比如移动硬盘拔出导致的硬件IO错误,流将无法再继续使用
  • failbit:表示操作失败,比如写入的数据格式不匹配,或者写入过程中设备断开
  • eofbit:表示到达文件末尾,和硬件拔出无关

使用fstream捕获移动硬盘拔出异常

首先需要开启fstream的异常抛出开关,默认情况下fstream不会抛出异常,只会设置状态位,开启后当对应状态位被设置时就会抛出std::ios_base::failure异常。

#include <fstream>
#include <iostream>
#include <exception>

int main() {
    // 打开移动硬盘上的文件,开启badbit和failbit的异常抛出
    std::ofstream out_file;
    out_file.exceptions(std::ofstream::badbit | std::ofstream::failbit);
    try {
        // 假设移动硬盘挂载路径为/media/usb/test.txt
        out_file.open("/media/usb/test.txt");
        if (!out_file.is_open()) {
            std::cout << "文件打开失败" << std::endl;
            return -1;
        }
        // 循环写入数据,模拟长时间写入场景
        for (int i = 0; i < 1000; ++i) {
            out_file << "这是第" << i << "行测试数据" << std::endl;
            // 每次写入后刷新缓冲区,模拟真实写入场景
            out_file.flush();
        }
        out_file.close();
        std::cout << "文件写入完成" << std::endl;
    } catch (const std::ios_base::failure& e) {
        // 捕获到IO异常,说明发生了比如移动硬盘拔出之类的错误
        std::cout << "捕获到IO异常:" << e.what() << std::endl;
        if (out_file.is_open()) {
            out_file.close();
        }
        return -1;
    } catch (const std::exception& e) {
        // 捕获其他标准异常
        std::cout << "捕获到其他异常:" << e.what() << std::endl;
        return -1;
    }
    return 0;
}

使用C标准库stdio捕获异常

如果使用C的stdio函数进行文件操作,没有异常机制,需要通过检查函数返回值和errno来判断是否发生错误,移动硬盘拔出后,fwrite等写入函数会返回小于预期写入数量的数值,同时errno会被设置为EIO。

#include <cstdio>
#include <cstring>
#include <cerrno>
#include <iostream>

int main() {
    // 打开移动硬盘上的文件
    FILE* fp = fopen("/media/usb/test.txt", "w");
    if (fp == nullptr) {
        std::cout << "文件打开失败,错误原因:" << strerror(errno) << std::endl;
        return -1;
    }
    char write_data[1024];
    memset(write_data, 'a', sizeof(write_data));
    // 循环写入数据
    for (int i = 0; i < 100; ++i) {
        // 写入1024字节数据
        size_t write_size = fwrite(write_data, 1, sizeof(write_data), fp);
        if (write_size != sizeof(write_data)) {
            // 写入数量不符合预期,说明发生错误
            std::cout << "写入失败,错误原因:" << strerror(errno) << std::endl;
            fclose(fp);
            return -1;
        }
        fflush(fp);
    }
    fclose(fp);
    std::cout << "文件写入完成" << std::endl;
    return 0;
}

避坑注意事项

在处理这类异常时,有几个常见的坑需要避免:

  • 不要忽略流的flush操作,移动硬盘写入有缓存,不主动刷新缓冲区的话,即使设备拔出,也可能因为数据还在内存缓存中没有显示错误,导致错误发现滞后
  • 捕获异常后一定要关闭打开的文件流,避免资源泄漏,即使流已经处于错误状态,关闭操作也是安全的
  • 不要假设写入成功就代表数据已经完整存储到移动硬盘,底层可能还有缓存,必要时可以做写入后的校验逻辑
  • 如果是跨平台程序,Windows和Linux下的错误信息描述不同,不要硬编码错误信息判断,尽量通过状态位或者errno数值判断

扩展:RAII方式封装文件操作

为了避免忘记关闭文件,可以使用RAII方式封装文件操作,在析构函数中自动关闭文件,同时结合异常捕获逻辑,让代码更健壮。

#include <fstream>
#include <iostream>
#include <exception>

class SafeFileWriter {
private:
    std::ofstream out_file;
public:
    SafeFileWriter(const char* file_path) {
        out_file.exceptions(std::ofstream::badbit | std::ofstream::failbit);
        out_file.open(file_path);
    }
    ~SafeFileWriter() {
        if (out_file.is_open()) {
            try {
                out_file.close();
            } catch (...) {
                // 析构函数中不要抛出异常,吞掉关闭时的异常
            }
        }
    }
    void write_line(const std::string& line) {
        out_file << line << std::endl;
        out_file.flush();
    }
};

int main() {
    try {
        SafeFileWriter writer("/media/usb/test.txt");
        for (int i = 0; i < 1000; ++i) {
            writer.write_line("这是第" + std::to_string(i) + "行测试数据");
        }
        std::cout << "文件写入完成" << std::endl;
    } catch (const std::ios_base::failure& e) {
        std::cout << "捕获到IO异常:" << e.what() << std::endl;
        return -1;
    }
    return 0;
}

C++_IO异常捕获文件写入异常处理移动硬盘拔出异常文件流错误处理修改时间:2026-06-15 12:51:24

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。