> 技术文档 > C++基础学习——文件操作详解_c++文件操作

C++基础学习——文件操作详解_c++文件操作


一、文件流类概述

C++ 标准库提供了三个主要的文件流类:

  1. ifstream (输入文件流):用于从文件读取数据
  2. ofstream (输出文件流):用于向文件写入数据
  3. fstream (文件流):既可读又可写

这些类都继承自 iostream 类,因此可以使用 <<>> 操作符进行格式化I/O操作。

二、文件打开与关闭

1. 打开文件

#include using namespace std;// 方法1:先声明再打开ofstream outFile;outFile.open(\"output.txt\");// 方法2:声明时直接打开ifstream inFile(\"input.txt\");// 方法3:使用fstreamfstream ioFile;ioFile.open(\"data.txt\", ios::in | ios::out);

2. 文件打开模式

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

组合示例:

// 以写入和追加模式打开ofstream logFile(\"log.txt\", ios::out | ios::app);// 以读写和二进制模式打开fstream dataFile(\"data.dat\", ios::in | ios::out | ios::binary);

3. 关闭文件

outFile.close();inFile.close();ioFile.close();

注意:虽然流对象析构时会自动关闭文件,但显式关闭是个好习惯。

三、文件状态检查

ifstream file(\"data.txt\");if (file.is_open()) { // 文件成功打开} else { // 文件打开失败}// 检查流状态if (file.good()) { // 流状态良好}if (file.fail()) { // 操作失败(非致命错误}if (file.bad()) { // 严重错误}if (file.eof()) { // 到达文件末尾}

四、文本文件操作

1. 写入文本文件

ofstream out(\"output.txt\");if (out.is_open()) { out << \"第一行文本\" << endl; out << 123 << \" \" << 3.14 << endl; out << \"这是另一行文本\" << endl; out.close();} else { cerr << \"无法打开文件!\" << endl;}

2. 读取文本文件

逐行读取:
ifstream in(\"input.txt\");string line;if (in.is_open()) { while (getline(in, line)) { cout << line << endl; } in.close();}
逐词读取:
ifstream in(\"input.txt\");string word;if (in.is_open()) { while (in >> word) { cout << word << endl; } in.close();}
格式化读取:
ifstream in(\"data.txt\");int id;double value;string name;if (in.is_open()) { while (in >> id >> value >> name) { cout << \"ID: \" << id << \", Value: \" << value  << \", Name: \" << name << endl; } in.close();}

五、二进制文件操作

1. 写入二进制数据

struct Record { int id; char name[50]; double salary;};Record emp = {101, \"John Doe\", 4500.50};ofstream out(\"employees.dat\", ios::binary);if (out.is_open()) { out.write(reinterpret_cast<char*>(&emp), sizeof(Record)); out.close();}

2. 读取二进制数据

Record emp;ifstream in(\"employees.dat\", ios::binary);if (in.is_open()) { in.read(reinterpret_cast<char*>(&emp), sizeof(Record)); cout << \"ID: \" << emp.id << endl; cout << \"Name: \" << emp.name << endl; cout << \"Salary: \" << emp.salary << endl; in.close();}

3. 二进制文件随机访问

fstream file(\"data.dat\", ios::in | ios::out | ios::binary);// 写入多个记录Record records[3] = { {101, \"Alice\", 5000}, {102, \"Bob\", 6000}, {103, \"Charlie\", 7000}};file.write(reinterpret_cast<char*>(records), 3 * sizeof(Record));// 直接读取第二个记录Record emp;file.seekg(1 * sizeof(Record), ios::beg);file.read(reinterpret_cast<char*>(&emp), sizeof(Record));// 修改第三个记录emp = {103, \"David\", 7500};file.seekp(2 * sizeof(Record), ios::beg);file.write(reinterpret_cast<char*>(&emp), sizeof(Record));file.close();

六、文件定位

1. 获取当前位置

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

2. 设置位置

// 绝对定位file.seekg(0, ios::beg); // 移动到文件开头file.seekg(0, ios::end); // 移动到文件末尾// 相对定位file.seekg(10, ios::cur); // 从当前位置向前移动10字节file.seekg(-5, ios::cur); // 从当前位置向后移动5字节

七、实用文件操作函数

1. 检查文件是否存在

#include bool fileExists(const string& filename) { struct stat buffer; return (stat(filename.c_str(), &buffer) == 0);}

2. 获取文件大小

streampos getFileSize(const string& filename) { ifstream file(filename, ios::ate | ios::binary); return file.tellg();}

3. 复制文件

bool copyFile(const string& source, const string& dest) { ifstream src(source, ios::binary); ofstream dst(dest, ios::binary); if (!src || !dst) { return false; } dst << src.rdbuf(); return true;}

4. 读取CSV文件

void readCSV(const string& filename) { ifstream file(filename); string line; while (getline(file, line)) { stringstream ss(line); string cell; vector<string> row; while (getline(ss, cell, \',\')) { row.push_back(cell); } // 处理行数据 for (const auto& val : row) { cout << val << \"\\t\"; } cout << endl; }}

八、错误处理最佳实践

void processFile(const string& filename) { ifstream file(filename); if (!file) { cerr << \"错误:无法打开文件 \" << filename << endl; perror(\"原因\"); // 打印系统错误信息 return; } try { // 文件处理代码 string line; while (getline(file, line)) { // 处理每一行 } if (file.bad()) { throw runtime_error(\"读取文件时发生严重错误\"); } if (file.fail() && !file.eof()) { throw runtime_error(\"文件格式错误\"); } } catch (const exception& e) { cerr << \"错误: \" << e.what() << endl; file.close(); return; } file.close();}

九、性能考虑

  1. 缓冲区大小:默认缓冲区大小可能不适合大文件操作,可以自定义:

    char buffer[8192]; // 8KB缓冲区ifstream file;file.rdbuf()->pubsetbuf(buffer, sizeof(buffer));file.open(\"largefile.dat\");
  2. 二进制 vs 文本:二进制操作通常比文本操作更快,特别是对于大量数据。

  3. 内存映射文件:对于极大文件,考虑使用操作系统特定的内存映射文件API。

十、C++17 文件系统库

C++17 引入了 库,提供了更高级的文件操作:

#include namespace fs = std::filesystem;// 检查文件是否存在if (fs::exists(\"test.txt\")) { // 获取文件大小 auto size = fs::file_size(\"test.txt\"); // 复制文件 fs::copy(\"source.txt\", \"destination.txt\"); // 删除文件 fs::remove(\"old_file.txt\"); // 遍历目录 for (auto& entry : fs::directory_iterator(\".\")) { cout << entry.path() << endl; }}

通过掌握这些文件操作技术,您可以在C++程序中高效地处理各种文件I/O任务。