欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > 能源 > C++ —— 文件操作(流式操作)

C++ —— 文件操作(流式操作)

2025/4/9 16:10:15 来源:https://blog.csdn.net/qq_67693066/article/details/146980480  浏览:    关键词:C++ —— 文件操作(流式操作)

C++ —— 文件操作(流式操作)

  • ofstream
    • 文件创建
    • 文件写入
  • ofstream 文件打开模式
    • std::ios::out 写入模式
    • std::ios::app 追加模式
    • std::ios::trunc 截断
    • std::ios::binary 二进制
    • std::ios::ate at the end模式
  • ifstream
    • std::ios::in 读取模式(默认)
    • std::ios::binary
    • 模式组合
      • 常见组合
    • 特殊模式说明
    • std::ios::ate (At End)
    • 重要注意事项
    • 完整示例
    • 模式总结表
  • fstream
  • C++ `fstream` 文件流详解
    • 基本用法
      • 1. 头文件
      • 2. 打开文件
      • 3. 检查文件是否成功打开
    • 文件打开模式
    • 读写操作
      • 写入文件
      • 读取文件
      • 二进制读写
    • 文件指针控制
      • 获取当前位置
      • 移动指针
    • 完整示例
    • 注意事项
  • 文件流的成员函数
      • **1. 打开/关闭文件**
      • **2. 状态检查**
      • **3. 读写操作**
        • **基本读写**
        • **二进制读写**
      • **4. 文件指针操作**
      • **5. 其他功能**
      • **示例代码**
      • **注意事项**
  • 流式文件操作和一般的文件操作函数区别
      • **1. 设计理念**
      • **2. 使用方式对比**
        • **(1)打开文件**
        • **(2)读写数据**
        • **(3)关闭文件**
      • **3. 核心区别**
      • **4. 适用场景**
        • **优先使用流式操作的情况**
        • **优先使用一般函数的情况**
      • **5. 代码示例对比**
        • **示例 1:复制文本文件**
        • **示例 2:读取二进制数据**
      • **总结**

我们之前已经了解过了C语言的文件操作,如果大家对着一块不是很了解的话,可以点击这里:

https://blog.csdn.net/qq_67693066/article/details/135588933?spm=1011.2415.3001.5331

我们来看看C++对于文件操作是怎么办的:

ofstream

在这里插入图片描述
ofstream(Output File Stream)是 C++ 中用于写入文件的类,属于 fstream 库。

文件创建

int main()
{std::ofstream file("myfile.txt");//检查是否创建成功// 检查是否创建成功if (!file) {std::cout << "文件创建失败!";return 1;}std::cout << "文件创建成功!";return 0;
}

运行成功的话,可以在项目的路径下看见新创建的文件:
在这里插入图片描述

文件写入

ofstream的写入直接用 << 就可以了:

int main()
{std::ofstream file("myfile.txt");if (file) {file << "姓名: 张三\n";     // 写入字符串file << "年龄: " << 25 << "\n";  // 混合写入file << "身高: " << 175.5 << "cm\n";}return 0;
}

在这里插入图片描述

ofstream 文件打开模式

ofstream 提供了多种文件打开模式,通过位掩码(std::ios 中的枚举)组合使用:

std::ios::out 写入模式

std::ios::out,文件存在时会清空文件内容,文件不存在的话会创建新的文件,我们可以来试验一下,我刚刚在前面的介绍中往文件中写入了一些文字:
在这里插入图片描述我们重新执行一次代码:

int main()
{std::ofstream file("myfile.txt",std::ios::out); //默认模式return 0;
}

在这里插入图片描述

std::ios::app 追加模式

std::ios::app允许你在创建完文件之后,之后再次往文件当中追加内容:

int main()
{//std::ofstream file("myfile.txt",std::ios::out); //默认模式std::ofstream file("myfile.txt", std::ios::app);if (file){file << "I am wiriting\n";}return 0;
}

在这里插入图片描述

std::ios::trunc 截断

如果文件已存在,清空文件内容(与 ios::out 默认行为相同)

int main()
{//std::ofstream file("myfile.txt",std::ios::out); //默认模式//std::ofstream file("myfile.txt", std::ios::app);std::ofstream file("myfile.txt", std::ios::trunc);return 0;
}

在这里插入图片描述

std::ios::binary 二进制

std::ios::binary 是 C++ 文件流的一个打开模式,用于以二进制形式读写文件,避免文本模式下的字符转换:

适用场景:

  • 读写非文本文件(如图片、音频、视频、压缩包等)。
  • 精确控制文件内容,避免文本模式下的自动转换。
int main()
{// 以二进制模式写入文件(如果文件存在,会被覆盖)std::ofstream file("data.bin", std::ios::binary | std::ios::out);if (!file) {std::cerr << "Failed to open file!" << std::endl;return 1;}int num = 12345;double pi = 3.14159;char str[] = "Hello Binary!";// 直接写入二进制数据file.write(reinterpret_cast<const char*>(&num), sizeof(num));file.write(reinterpret_cast<const char*>(&pi), sizeof(pi));file.write(str, sizeof(str)); // 包括 '\0' 结束符file.close();std::cout << "Binary data written to data.bin" << std::endl;}

std::ios::ate at the end模式

std::ios::ate 创建之后文件指针的位置就会放在最后,并且可以通过seekp来移动文件指针位置,重新输入内容:

int main()
{std::ofstream file("myfile.txt", std::ios::ate);file << "I am writing " << endl;file.seekp(3);file << "This is a another setence " << endl;return 0;
}

在这里插入图片描述

ifstream

std::ifstream 是 C++ 标准库中专门用于从文件读取数据的输入流类,继承自 std::istream。它是文件操作三大类之一(另外两个是 ofstream 和 fstream)。
在这里插入图片描述

std::ios::in 读取模式(默认)

std::ios::in 以读取模式打开,文件必须存在,否则会失败:

#include<fstream>int main()
{std::ofstream file1("myfile.txt", std::ios::ate);file1 << "I am writing " << endl;file1.seekp(3);file1 << "This is a another setence " << endl;std::ifstream file2("myfile.txt", std::ios::in);//获取文件大小file2.seekg(0, std::ios::end);std::streampos fileSize = file2.tellg();file2.seekg(0);std::cout << "文件大小: " << fileSize << " 字节" << std::endl;char* buffer = new char[1024*1024]; file2.read(buffer, fileSize);buffer[fileSize] = '\0'; // 添加终止符printf("%s\n", buffer);return 0;
}

在这里插入图片描述

std::ios::binary

  • 作用:以二进制模式打开文件
  • 特点
    • 避免文本模式下的字符转换(如换行符转换)
    • 适合读取非文本文件(如图片、视频等)
  • 示例
    std::ifstream binFile("image.jpg", std::ios::binary);
    

模式组合

可以组合多个模式使用,使用按位或运算符 |

常见组合

  1. 普通文本读取

    std::ifstream textFile("text.txt", std::ios::in);
    
  2. 二进制读取

    std::ifstream binFile("data.bin", std::ios::in | std::ios::binary);
    
  3. 从文件末尾开始读取

    std::ifstream file("log.txt", std::ios::in | std::ios::ate);
    

特殊模式说明

std::ios::ate (At End)

  • 作用:打开文件后立即定位到文件末尾
  • 特点
    • 可以先用 tellg() 获取文件大小
    • 之后可以用 seekg() 移动到任意位置读取
  • 示例
    std::ifstream file("data.txt", std::ios::in | std::ios::ate);
    if (file.is_open()) {std::streampos size = file.tellg(); // 获取文件大小file.seekg(0); // 回到文件开头开始读取// ...读取操作...
    }
    

重要注意事项

  1. 文件不存在

    • 如果文件不存在且只使用 std::ios::in,打开会失败
    • 检查是否成功打开:
      if (!file.is_open()) {// 处理错误
      }
      
  2. 模式兼容性

    • ifstream 不支持写入模式(如 std::ios::out
    • 如果需要写入,应使用 fstream
  3. 二进制模式

    • 在Windows平台上,文本模式会自动转换 \r\n\n
    • 二进制模式保持原始字节不变
  4. 默认行为

    • 如果不指定任何模式,默认是 std::ios::in
    • 如果不指定二进制模式,默认是文本模式

完整示例

#include <fstream>
#include <iostream>int main() {// 以二进制模式打开文件并从末尾开始std::ifstream file("data.dat", std::ios::in | std::ios::binary | std::ios::ate);if (!file.is_open()) {std::cerr << "无法打开文件" << std::endl;return 1;}// 获取文件大小std::streampos fileSize = file.tellg();std::cout << "文件大小: " << fileSize << " 字节" << std::endl;// 回到文件开头file.seekg(0, std::ios::beg);// 读取文件内容char* buffer = new char[fileSize];file.read(buffer, fileSize);// 处理数据...delete[] buffer;file.close();return 0;
}

模式总结表

模式标志描述适用场景
std::ios::in读取模式(默认)普通文本文件读取
std::ios::binary二进制模式非文本文件读取
std::ios::ate打开后定位到文件末尾需要先获取文件大小的场景

fstream

在这里插入图片描述
fstream其实是ofstream和ifstream的结合:

C++ fstream 文件流详解

fstream 是 C++ 标准库中用于文件输入输出的流类,它结合了 ifstream(输入)和 ofstream(输出)的功能,允许对文件进行读写操作。

基本用法

1. 头文件

#include <fstream>

2. 打开文件

std::fstream file;
file.open("example.txt", std::ios::in | std::ios::out);

或者直接初始化:

std::fstream file("example.txt", std::ios::in | std::ios::out);

3. 检查文件是否成功打开

if (!file.is_open()) {std::cerr << "无法打开文件" << std::endl;return 1;
}

文件打开模式

fstream 支持多种打开模式,可以用位或运算符 | 组合:

模式标志描述
std::ios::in读取模式(文件必须存在)
std::ios::out写入模式(创建或覆盖文件)
std::ios::app追加模式(所有写入在文件末尾)
std::ios::ate打开后定位到文件末尾
std::ios::binary二进制模式(避免字符转换)
std::ios::trunc如果文件存在,先清空内容

读写操作

写入文件

file << "写入一行文本\n";
file << "数字: " << 42 << std::endl;

读取文件

std::string line;
while (std::getline(file, line)) {std::cout << line << std::endl;
}

二进制读写

// 写入二进制数据
int data = 12345;
file.write(reinterpret_cast<char*>(&data), sizeof(data));// 读取二进制数据
int readData;
file.read(reinterpret_cast<char*>(&readData), sizeof(readData));

文件指针控制

获取当前位置

std::streampos pos = file.tellg();  // 获取读取位置
pos = file.tellp();                 // 获取写入位置

移动指针

file.seekg(0, std::ios::beg);  // 将读取指针移动到文件开头
file.seekp(10, std::ios::cur); // 将写入指针从当前位置移动10字节

完整示例

#include <fstream>
#include <iostream>
#include <string>int main() {// 打开文件用于读写(不存在则创建)std::fstream file("data.txt", std::ios::in | std::ios::out | std::ios::trunc);if (!file.is_open()) {std::cerr << "无法打开文件" << std::endl;return 1;}// 写入数据file << "第一行\n";file << "第二行\n";file << 123 << " " << 3.14 << std::endl;// 回到文件开头读取file.seekg(0);std::string line;while (std::getline(file, line)) {std::cout << "读取到: " << line << std::endl;}file.close();return 0;
}

注意事项

  1. 模式组合fstream 没有默认模式,必须显式指定 inout
  2. 文件存在性:使用 in 模式时文件必须存在
  3. 二进制模式:处理非文本文件时应使用 binary 模式
  4. 指针同步:读写切换时需要调用 seekg()seekp()
  5. 内存管理:使用 write() 写入二进制数据时要注意数据对齐

fstream 提供了灵活的文件操作能力,适合需要同时读写文件的场景。对于简单的只读或只写操作,可以考虑使用 ifstreamofstream

文件流的成员函数

在 C++ 中,文件流相关的类(如 ifstream, ofstream, fstream)提供了许多成员函数来操作文件。以下是常见的文件流成员函数分类说明:


1. 打开/关闭文件

  • open()
    打开文件,与流关联。

    void open(const char* filename, ios_base::openmode mode = ios_base::in | ios_base::out);
    
    • filename:文件路径
    • mode:打开模式(如 ios::in, ios::out, ios::binary, ios::app 等)。
  • close()
    关闭文件,释放资源。

    void close();
    

2. 状态检查

  • is_open()
    检查文件是否成功打开。

    bool is_open() const;
    
  • good() / eof() / fail() / bad()
    检查流状态:

    • good():操作是否正常(无错误)。
    • eof():是否到达文件末尾(End-of-File)。
    • fail():操作是否失败(可恢复错误,如类型不匹配)。
    • bad():是否发生严重错误(如文件损坏)。

3. 读写操作

基本读写
  • >> (提取运算符)
    从文件读取数据(格式化输入)。

    ifstream file("input.txt");
    int value;
    file >> value; // 读取一个整数
    
  • << (插入运算符)
    向文件写入数据(格式化输出)。

    ofstream file("output.txt");
    file << "Hello, World!" << endl;
    
二进制读写
  • read()
    从文件读取二进制数据。

    istream& read(char* buffer, streamsize size);
    
    • buffer:存储数据的缓冲区。
    • size:要读取的字节数。
  • write()
    向文件写入二进制数据。

    ostream& write(const char* buffer, streamsize size);
    

4. 文件指针操作

  • tellg() / tellp()
    获取当前读写位置:

    • tellg():返回输入流(读)的指针位置(ifstream)。
    • tellp():返回输出流(写)的指针位置(ofstream)。
  • seekg() / seekp()
    移动文件指针:

    istream& seekg(streampos pos); // 移动到绝对位置
    istream& seekg(streamoff offset, ios_base::seekdir dir); // 相对位置移动
    
    • pos:绝对位置。
    • offset:偏移量。
    • dir:基准位置(ios::beg 开头,ios::cur 当前位置,ios::end 结尾)。

5. 其他功能

  • flush()
    强制刷新输出缓冲区(立即写入文件)。

    ostream& flush();
    
  • peek()
    查看下一个字符但不移动指针。

    int peek();
    
  • get() / getline()
    读取字符或一行:

    int get(); // 读取单个字符
    istream& getline(char* buffer, streamsize size); // 读取一行
    

示例代码

#include <fstream>
#include <iostream>
using namespace std;int main() {// 写入文件ofstream out("test.txt");if (out.is_open()) {out << "Line 1\nLine 2" << endl;out.close();}// 读取文件ifstream in("test.txt");if (in.is_open()) {string line;while (getline(in, line)) {cout << line << endl;}in.close();}return 0;
}

注意事项

  1. 模式标志
    • ios::in(读)、ios::out(写)、ios::binary(二进制)、ios::app(追加)等可组合使用。
  2. 错误处理
    始终检查 is_open()good() 避免未定义行为。
  3. 资源释放
    显式调用 close() 或依赖析构函数自动关闭。

根据需求选择合适的函数组合即可高效操作文件!

流式文件操作和一般的文件操作函数区别

在 C++ 中,流式文件操作(基于 fstream/ifstream/ofstream)和 一般文件操作函数(基于 C 语言的 FILE* 或系统 API)是两种不同的文件处理方式,它们在设计理念、使用方式和适用场景上有显著区别。以下是详细对比:


1. 设计理念

特性流式文件操作 (fstream 等)一般文件操作函数 (fopen/read/Write 等)
封装层次高级封装,面向对象(基于 std::iostream 类体系)低级封装,面向过程(函数调用)
数据视角将文件视为连续的字符流或对象序列将文件视为字节块或二进制数据
缓冲区管理自动缓冲(默认),支持手动刷新 (flush)需手动管理缓冲区(如 setvbuf
错误处理通过流状态标志(good(), fail())或异常机制通过返回值(如 NULL-1)和全局 errno

2. 使用方式对比

(1)打开文件
  • 流式操作
    #include <fstream>
    std::ifstream fin("input.txt", std::ios::binary); // 二进制模式
    std::ofstream fout("output.txt");
    
  • 一般函数
    #include <cstdio>
    FILE* fin = fopen("input.txt", "rb");  // C 风格
    int fd = open("input.txt", O_RDONLY);  // POSIX API
    
(2)读写数据
  • 流式操作(类型安全):
    int num;
    fin >> num;                  // 格式化读取(文本)
    fout << "Hello" << std::endl; // 格式化写入fin.read(buffer, size);       // 二进制读取
    fout.write(buffer, size);     // 二进制写入
    
  • 一般函数(直接操作字节):
    fscanf(fin, "%d", &num);     // C 格式化读取
    fprintf(fout, "Hello\n");fread(buffer, 1, size, fin); // C 二进制读取
    write(fd, buffer, size);     // POSIX 写入
    
(3)关闭文件
  • 流式操作(自动析构):
    fin.close(); // 可省略,析构时自动调用
    
  • 一般函数(需显式关闭):
    fclose(fin); // C 风格
    close(fd);   // POSIX
    

3. 核心区别

对比项流式文件操作一般文件操作函数
类型安全✅ 支持运算符重载(<</>>),避免类型错误❌ 需手动匹配格式字符串(如 %d vs %f
性能⚠️ 默认有缓冲,适合高频小数据量操作⚠️ 无缓冲时更快,适合大块二进制数据
灵活性❌ 高级封装,底层控制受限(如精确指针移动)✅ 直接操作文件描述符/指针,控制更精细
跨平台性✅ 标准 C++ 实现,跨平台一致⚠️ C 库跨平台,但系统 API(如 open)需适配
异常支持✅ 可通过 exceptions() 启用异常❌ 仅通过返回值/errno 处理错误

4. 适用场景

优先使用流式操作的情况
  • 需要 类型安全 的文本读写(如配置文件、日志)。
  • 代码已基于 C++ 标准库,希望保持风格统一。
  • 简单的逐行或格式化数据处理(如 getline 读取 CSV)。
优先使用一般函数的情况
  • 需要 高性能二进制操作(如大文件拷贝、网络数据传输)。
  • 依赖 系统特定功能(如文件锁、内存映射)。
  • 遗留项目或与 C 语言交互的代码。

5. 代码示例对比

示例 1:复制文本文件
  • 流式操作
    std::ifstream src("source.txt");
    std::ofstream dst("dest.txt");
    dst << src.rdbuf(); // 一行完成拷贝
    
  • 一般函数
    FILE* src = fopen("source.txt", "r");
    FILE* dst = fopen("dest.txt", "w");
    char buffer[4096];
    while (size_t len = fread(buffer, 1, sizeof(buffer), src)) {fwrite(buffer, 1, len, dst);
    }
    fclose(src); fclose(dst);
    
示例 2:读取二进制数据
  • 流式操作
    std::ifstream file("data.bin", std::ios::binary);
    int value;
    file.read(reinterpret_cast<char*>(&value), sizeof(value));
    
  • 一般函数
    FILE* file = fopen("data.bin", "rb");
    int value;
    fread(&value, sizeof(value), 1, file);
    

总结

  • 流式操作:适合 高层抽象类型安全 的场景,代码简洁但灵活性较低。
  • 一般函数:适合 底层控制高性能二进制处理,但需手动管理资源。

根据项目需求选择合适的方式,现代 C++ 项目推荐优先使用 <fstream>,除非有明确的性能或控制需求。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词