C++ 中打开文件的多种方式及相关流类

C++ 中打开文件的多种方式及相关流类

C++学习:

https://blog.ZEEKLOG.net/2301_80220607/category_12805124.html?spm=1001.2014.3001.5482

前言:

打开一个文件的方式都有哪些,都可以通过哪些流来获取它?



在 C++ 中,打开文件可以通过多种流类实现,每种方式都有其特定的用途和特点。以下是详细的分类和说明:

目录

1. 使用标准文件流类( )

1.1 ofstream - 输出文件流(写入)

1.2 ifstream - 输入文件流(读取)

1.3 fstream - 双向文件流(读写)

2. 使用 C 风格文件操作( )

3. 使用文件描述符(POSIX/unistd.h)

4. 使用内存映射文件(高级方式)

5. 文件打开模式详解

5.1 C++ 流打开模式(位掩码组合)

5.2 C 风格打开模式

6. 不同方式的比较

7. 最佳实践建议

8. 高级用法示例

8.1 同时读写文件

8.2 二进制文件操作


1. 使用标准文件流类(<fstream>)

1.1 ofstream - 输出文件流(写入)

#include <fstream> // 方式1:构造函数直接打开 std::ofstream outFile1("output.txt"); // 默认模式:ios::out | ios::trunc // 方式2:先创建后打开 std::ofstream outFile2; outFile2.open("output.txt", std::ios::app); // 追加模式 // 写入数据 outFile1 << "Hello World" << std::endl;

1.2 ifstream - 输入文件流(读取)

#include <fstream> // 方式1:构造函数直接打开 std::ifstream inFile1("input.txt"); // 默认模式:ios::in // 方式2:先创建后打开 std::ifstream inFile2; inFile2.open("input.txt"); // 读取数据 std::string line; while (std::getline(inFile2, line)) { std::cout << line << std::endl; }

1.3 fstream - 双向文件流(读写)

#include <fstream> // 读写模式 std::fstream ioFile("data.txt", std::ios::in | std::ios::out); // 读写二进制文件 std::fstream binFile("data.bin", std::ios::binary | std::ios::in | std::ios::out);

2. 使用 C 风格文件操作(<cstdio>)

#include <cstdio> // 打开方式 FILE* file = fopen("file.txt", "r"); // 读取 FILE* file = fopen("file.txt", "w"); // 写入(清空) FILE* file = fopen("file.txt", "a"); // 追加 FILE* file = fopen("file.bin", "rb"); // 二进制读取 if (file != nullptr) { // 使用文件... fclose(file); // 必须手动关闭 }

3. 使用文件描述符(POSIX/unistd.h)

#include <unistd.h> #include <fcntl.h> int fd = open("file.txt", O_RDONLY); // 只读 int fd = open("file.txt", O_WRONLY | O_CREAT, 0644); // 写入+创建 if (fd != -1) { char buffer[1024]; read(fd, buffer, sizeof(buffer)); close(fd); // 必须手动关闭 }

4. 使用内存映射文件(高级方式)

#include <sys/mman.h> #include <fcntl.h> #include <unistd.h> int fd = open("largefile.bin", O_RDONLY); void* mapped = mmap(nullptr, file_size, PROT_READ, MAP_PRIVATE, fd, 0); // 使用映射的内存区域... munmap(mapped, file_size); close(fd);

5. 文件打开模式详解

5.1 C++ 流打开模式(位掩码组合)

模式标志描述
std::ios::in读取模式
std::ios::out写入模式
std::ios::app追加写入
std::ios::ate打开后定位到文件末尾
std::ios::trunc如果文件存在则清空
std::ios::binary二进制模式

5.2 C 风格打开模式

模式描述
"r"只读
"w"只写(创建/清空)
"a"追加写入
"r+"读写
"w+"读写(创建/清空)
"a+"读和追加

6. 不同方式的比较

特性C++ 流C 文件操作文件描述符
面向对象
类型安全
自动资源管理
格式化I/O
二进制I/O
低级控制部分
跨平台基本✓
性能中等较高最高

7. 最佳实践建议

  1. 常规文本文件操作:优先使用 C++ 文件流(fstream/ofstream/ifstream
  2. 高性能需求:考虑使用 C 风格文件操作或文件描述符
  3. 二进制文件:总是使用 std::ios::binary 标志
  4. 资源管理:使用 RAII 原则,推荐 C++ 流自动管理资源

错误检查:始终检查文件是否成功打开

std::ofstream file("data.txt"); if (!file.is_open()) { // 错误处理 }

8. 高级用法示例

8.1 同时读写文件

std::fstream file("data.txt", std::ios::in | std::ios::out | std::ios::ate); // 打开并定位到末尾 if (file) { // 读取当前位置 std::streampos endPos = file.tellg(); // 回到开头读取 file.seekg(0); std::string content; std::getline(file, content); // 写入新数据 file << "\nNew data appended"; }

8.2 二进制文件操作

struct Record { int id; char name[50]; double value; }; // 写入二进制 std::ofstream binOut("data.bin", std::ios::binary); Record rec{1, "Test", 3.14}; binOut.write(reinterpret_cast<char*>(&rec), sizeof(Record)); // 读取二进制 std::ifstream binIn("data.bin", std::ios::binary); Record inRec; binIn.read(reinterpret_cast<char*>(&inRec), sizeof(Record));

选择哪种方式取决于具体需求,C++ 文件流提供了最安全和方便的方式,而 C 风格和文件描述符则提供了更多的控制和更高的性能。

Read more

Java 线程池线程数怎么定?从 IO / CPU / 混合型任务谈起

Java 线程池线程数怎么定?从 IO / CPU / 混合型任务谈起

文章目录 * 1. 按照任务类型对线程池进行分类 * 2. 为 IO 密集型任务确定线程数 * 3. 为 CPU 密集型任务确定线程数 * 4. 为混合型任务确定线程数 在实际开发中,线程池几乎是每个 Java 后端绕不开的组件。但真正让人困惑的往往不是怎么用线程池,而是——线程数到底该怎么配。 有人按 CPU 核数来,有人直接乘 2,还有人干脆拍脑袋设一个固定值。这些做法在某些场景下 “看起来能跑”,但在 IO 较多或混合型任务中,往往会带来性能下降、请求堆积,甚至线程池耗尽的问题。 这篇文章主要面向 Java 后端开发者,结合常见的 IO 密集型、CPU 密集型以及混合型任务,梳理线程池线程数配置的基本思路,并给出可参考的计算方式,帮助你在不同场景下做出更合理的选择。 1. 按照任务类型对线程池进行分类 在讨论线程数之前,首先需要明确一点:线程数的配置和任务类型是强相关的。

By Ne0inhk
零代码AI革命:万字实战指南,用Dify轻松构建企业级智能知识库

零代码AI革命:万字实战指南,用Dify轻松构建企业级智能知识库

前言 在当今这个信息爆炸的时代,数据已成为企业和个人的核心资产。然而,如何从浩如烟海的文档、报告、手册和笔记中,高效、精准地提取所需信息,已成为一个普遍存在的痛点。传统的关键词搜索,面对复杂和口语化的查询时常常显得力不从心,无法真正理解用户的深层意图。我们迫切需要一种更智能、更接近自然语言交互的解决方案。 当下普遍存在的几大痛点: 1. 知识孤岛与检索困境: 企业内部的知识散落在不同的系统(如 Confluence, SharePoint, 本地文件夹)中,形成一个个信息孤岛。员工,尤其是新员工,为了找到一个问题的答案,可能需要在多个平台之间来回切换,耗费大量时间,效率低下。 2. AI 技术应用门槛高昂: 大语言模型(LLM)的出现为解决上述问题带来了曙光。但对于大多数非 AI 专业的开发者和中小企业而言,从零开始部署、微调、管理一个大模型,并将其封装成可用的应用,涉及到复杂的后端开发、算法知识、GPU 资源管理和高昂的运维成本,是一项几乎不可能完成的任务。 3.

By Ne0inhk
JavaScript 中生成 UUID及常见问题

JavaScript 中生成 UUID及常见问题

目录 描述 要点总结 什么是UUID?为什么要使用它? 现代方法:crypto.randomUUID() 浏览器实现 Node.js 实现 备用方法:crypto.getRandomValues() uuid npm 包,实现最大灵活性 安装 基本用法(UUID v4) 其他 UUID 版本 何时避免使用 Math.random() 最佳实践和验证 UUID验证 选择合适的方法 结论 常见问题解答 UUID v4 和 v5 有什么区别? 可以在 React Native 中使用 crypto.randomUUID() 吗? 如何生成简短的唯一 ID 而不是完整的 UUID?

By Ne0inhk
Java 中间件:RocketMQ 顺序消息(全局/分区顺序)

Java 中间件:RocketMQ 顺序消息(全局/分区顺序)

👋 大家好,欢迎来到我的技术博客! 📚 在这里,我会分享学习笔记、实战经验与技术思考,力求用简单的方式讲清楚复杂的问题。 🎯 本文将围绕Java中间件这个话题展开,希望能为你带来一些启发或实用的参考。 🌱 无论你是刚入门的新手,还是正在进阶的开发者,希望你都能有所收获! 文章目录 * Java 中间件:RocketMQ 顺序消息(全局 / 分区顺序) * 什么是顺序消息? * RocketMQ 顺序消息的工作原理 * 全局顺序 vs 分区顺序 * RocketMQ 顺序消息的核心机制 * 全局顺序消息的实现 * 全局顺序的配置要求 * Java 代码示例:全局顺序消息 * 全局顺序的局限性 * 分区顺序消息的实现 * 分区顺序的设计思路 * Java 代码示例:分区顺序消息 * 分区顺序的关键要点 * 顺序消息的消费机制详解 * ConsumeOrderlyStatus 枚举 * 消费失败的处理机制 * 并发消费 vs 顺序消费

By Ne0inhk