Appearance
文件操作
文件操作是程序与外部存储交互的重要方式。本章将介绍C++的文件流类、文件读写操作和文件定位等内容。
文件流基础
cpp
#include <iostream>
#include <fstream> // 文件流头文件
#include <string>
using namespace std;
/*
* C++文件流类层次:
*
* ios_base(基类)
* └── ios
* ├── istream(输入流)
* │ └── ifstream(文件输入流)
* ├── ostream(输出流)
* │ └── ofstream(文件输出流)
* └── iostream(输入输出流)
* └── fstream(文件输入输出流)
*/
int main() {
// ============ 文件打开模式 ============
/*
* 文件打开模式:
*
* ios::in - 读模式
* ios::out - 写模式
* ios::app - 追加模式
* ios::ate - 打开后定位到文件末尾
* ios::trunc - 截断文件(清空内容)
* ios::binary - 二进制模式
*
* 可以组合使用:ios::out | ios::app
*/
// ============ 写入文件 ============
// 方式1:构造时打开
ofstream outFile1("output1.txt");
// 方式2:先创建再打开
ofstream outFile2;
outFile2.open("output2.txt");
// 检查是否成功打开
if (!outFile1) {
cerr << "无法打开文件" << endl;
return 1;
}
// 写入数据
outFile1 << "Hello, File!" << endl;
outFile1 << "这是第二行" << endl;
outFile1 << "数字: " << 12345 << endl;
// 关闭文件
outFile1.close();
outFile2.close();
cout << "文件写入完成" << endl;
// ============ 读取文件 ============
ifstream inFile("output1.txt");
if (!inFile) {
cerr << "无法打开文件进行读取" << endl;
return 1;
}
cout << "\n===== 读取文件内容 =====" << endl;
// 方式1:逐行读取
string line;
while (getline(inFile, line)) {
cout << line << endl;
}
inFile.close();
// ============ 追加写入 ============
ofstream appendFile("output1.txt", ios::app);
if (appendFile) {
appendFile << "\n这是追加的内容" << endl;
appendFile.close();
cout << "\n追加写入完成" << endl;
}
return 0;
}文本文件操作
cpp
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;
int main() {
// ============ 写入文本文件 ============
ofstream outFile("students.txt");
if (!outFile) {
cerr << "无法创建文件" << endl;
return 1;
}
// 写入表头
outFile << "姓名\t年龄\t分数" << endl;
outFile << "----\t----\t----" << endl;
// 写入数据
vector<tuple<string, int, double>> students = {
{"张三", 20, 95.5},
{"李四", 21, 88.0},
{"王五", 19, 92.5}
};
for (const auto& student : students) {
outFile << get<0>(student) << "\t"
<< get<1>(student) << "\t"
<< get<2>(student) << endl;
}
outFile.close();
cout << "学生数据写入完成" << endl;
// ============ 读取文本文件 ============
ifstream inFile("students.txt");
if (!inFile) {
cerr << "无法打开文件" << endl;
return 1;
}
cout << "\n===== 读取学生数据 =====" << endl;
string line;
int lineNum = 0;
while (getline(inFile, line)) {
lineNum++;
// 跳过表头
if (lineNum <= 2) {
cout << line << endl;
continue;
}
// 解析数据行
istringstream iss(line);
string name;
int age;
double score;
if (iss >> name >> age >> score) {
cout << "解析: " << name << ", " << age << "岁, " << score << "分" << endl;
}
}
inFile.close();
// ============ 读写同一个文件 ============
fstream file("data.txt", ios::in | ios::out | ios::trunc);
if (!file) {
cerr << "无法打开文件" << endl;
return 1;
}
// 写入数据
file << "第一行" << endl;
file << "第二行" << endl;
file << "第三行" << endl;
// 定位到文件开头
file.seekg(0, ios::beg);
// 读取数据
cout << "\n===== 读写同一文件 =====" << endl;
string content;
while (getline(file, content)) {
cout << content << endl;
}
file.close();
return 0;
}二进制文件操作
cpp
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
// 定义一个结构体
struct Person {
char name[50];
int age;
double height;
};
int main() {
// ============ 写入二进制文件 ============
ofstream outFile("people.dat", ios::binary);
if (!outFile) {
cerr << "无法创建二进制文件" << endl;
return 1;
}
// 准备数据
Person people[] = {
{"张三", 25, 175.5},
{"李四", 30, 180.0},
{"王五", 28, 172.0}
};
// 写入二进制数据
// write(指针, 字节数)
for (const auto& p : people) {
outFile.write(reinterpret_cast<const char*>(&p), sizeof(Person));
}
outFile.close();
cout << "二进制数据写入完成" << endl;
// ============ 读取二进制文件 ============
ifstream inFile("people.dat", ios::binary);
if (!inFile) {
cerr << "无法打开二进制文件" << endl;
return 1;
}
cout << "\n===== 读取二进制数据 =====" << endl;
Person p;
while (inFile.read(reinterpret_cast<char*>(&p), sizeof(Person))) {
cout << "姓名: " << p.name << endl;
cout << "年龄: " << p.age << endl;
cout << "身高: " << p.height << endl;
cout << "---" << endl;
}
inFile.close();
// ============ 文件定位 ============
fstream file("people.dat", ios::in | ios::out | ios::binary);
if (!file) {
cerr << "无法打开文件" << endl;
return 1;
}
// 获取文件大小
file.seekg(0, ios::end);
streampos fileSize = file.tellg();
cout << "\n文件大小: " << fileSize << " 字节" << endl;
// 定位到第二条记录
file.seekg(sizeof(Person), ios::beg);
Person p2;
file.read(reinterpret_cast<char*>(&p2), sizeof(Person));
cout << "\n第二条记录: " << p2.name << ", " << p2.age << "岁" << endl;
// 修改第二条记录
p2.age = 35;
file.seekp(sizeof(Person), ios::beg); // 定位写位置
file.write(reinterpret_cast<char*>(&p2), sizeof(Person));
file.close();
cout << "\n修改完成" << endl;
return 0;
}文件操作实例
cpp
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;
// 文件复制函数
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;
}
// 统计文件信息
void fileStats(const string& filename) {
ifstream file(filename);
if (!file) {
cerr << "无法打开文件: " << filename << endl;
return;
}
int lines = 0;
int words = 0;
int chars = 0;
string line;
while (getline(file, line)) {
lines++;
chars += line.length() + 1; // +1 for newline
// 统计单词数
bool inWord = false;
for (char c : line) {
if (isspace(c)) {
inWord = false;
} else if (!inWord) {
inWord = true;
words++;
}
}
}
cout << "文件统计 (" << filename << "):" << endl;
cout << " 行数: " << lines << endl;
cout << " 单词数: " << words << endl;
cout << " 字符数: " << chars << endl;
}
// 查找文件中的字符串
vector<int> findInFile(const string& filename, const string& target) {
ifstream file(filename);
vector<int> lineNumbers;
if (!file) {
return lineNumbers;
}
string line;
int lineNum = 0;
while (getline(file, line)) {
lineNum++;
if (line.find(target) != string::npos) {
lineNumbers.push_back(lineNum);
}
}
return lineNumbers;
}
int main() {
// 创建测试文件
ofstream testFile("test.txt");
testFile << "Hello World" << endl;
testFile << "This is a test file" << endl;
testFile << "Hello C++" << endl;
testFile << "Programming is fun" << endl;
testFile << "Hello again" << endl;
testFile.close();
// 文件复制
cout << "===== 文件复制 =====" << endl;
if (copyFile("test.txt", "test_copy.txt")) {
cout << "复制成功" << endl;
}
// 文件统计
cout << "\n===== 文件统计 =====" << endl;
fileStats("test.txt");
// 查找字符串
cout << "\n===== 查找字符串 =====" << endl;
string target = "Hello";
vector<int> found = findInFile("test.txt", target);
cout << "\"" << target << "\" 出现在以下行: ";
for (int n : found) {
cout << n << " ";
}
cout << endl;
return 0;
}本章小结
本章学习了:
- 文件流类:ifstream、ofstream、fstream
- 打开模式:in、out、app、binary等
- 文本文件:读写文本数据
- 二进制文件:read、write、文件定位
- 文件操作实例:复制、统计、查找
下一章,我们将学习内存管理,了解C++的动态内存分配。
