C++ 文件和流
概述
C++提供了强大的I/O流系统来处理文件和数据流操作。流(Stream)是数据传输的抽象概念,文件操作是流的重要应用。本章介绍文件读写、流操作、格式化输入输出等内容。
📁 文件操作基础
文件读写
cpp
#include <iostream>
#include <fstream>
#include <string>
int main() {
std::cout << "=== 基本文件操作 ===" << std::endl;
// 写入文件
std::ofstream outFile("example.txt");
if (outFile.is_open()) {
outFile << "Hello, World!" << std::endl;
outFile << "这是第二行文本" << std::endl;
outFile << "数字: " << 42 << std::endl;
outFile.close();
std::cout << "文件写入成功" << std::endl;
}
// 读取文件
std::ifstream inFile("example.txt");
if (inFile.is_open()) {
std::string line;
std::cout << "文件内容:" << std::endl;
while (std::getline(inFile, line)) {
std::cout << line << std::endl;
}
inFile.close();
} else {
std::cout << "无法打开文件" << std::endl;
}
return 0;
}文件模式和状态
cpp
#include <iostream>
#include <fstream>
#include <string>
class FileHandler {
public:
static void writeTextFile(const std::string& filename, const std::string& content) {
std::ofstream file(filename, std::ios::out | std::ios::trunc);
if (!file) {
throw std::runtime_error("无法创建文件: " + filename);
}
file << content;
if (file.fail()) {
throw std::runtime_error("写入文件失败");
}
std::cout << "文件 " << filename << " 写入成功" << std::endl;
}
static std::string readTextFile(const std::string& filename) {
std::ifstream file(filename, std::ios::in);
if (!file) {
throw std::runtime_error("无法打开文件: " + filename);
}
std::string content;
std::string line;
while (std::getline(file, line)) {
content += line + "\n";
}
if (file.bad()) {
throw std::runtime_error("读取文件时发生错误");
}
return content;
}
static void appendToFile(const std::string& filename, const std::string& content) {
std::ofstream file(filename, std::ios::out | std::ios::app);
if (!file) {
throw std::runtime_error("无法打开文件进行追加: " + filename);
}
file << content;
std::cout << "内容已追加到 " << filename << std::endl;
}
};
int main() {
std::cout << "=== 文件模式和状态 ===" << std::endl;
try {
// 写入文件
FileHandler::writeTextFile("test.txt", "第一行内容\n第二行内容\n");
// 读取文件
std::string content = FileHandler::readTextFile("test.txt");
std::cout << "读取的内容:\n" << content << std::endl;
// 追加内容
FileHandler::appendToFile("test.txt", "追加的内容\n");
// 再次读取
content = FileHandler::readTextFile("test.txt");
std::cout << "追加后的内容:\n" << content << std::endl;
} catch (const std::exception& e) {
std::cout << "错误: " << e.what() << std::endl;
}
return 0;
}🌊 流操作
字符串流
cpp
#include <iostream>
#include <sstream>
#include <string>
class StringStreamDemo {
public:
static void inputStringStream() {
std::cout << "=== 输入字符串流 ===" << std::endl;
std::string data = "123 45.67 hello world";
std::istringstream iss(data);
int num;
double decimal;
std::string word1, word2;
iss >> num >> decimal >> word1 >> word2;
std::cout << "整数: " << num << std::endl;
std::cout << "小数: " << decimal << std::endl;
std::cout << "单词1: " << word1 << std::endl;
std::cout << "单词2: " << word2 << std::endl;
}
static void outputStringStream() {
std::cout << "\n=== 输出字符串流 ===" << std::endl;
std::ostringstream oss;
oss << "数字: " << 42;
oss << ", 小数: " << 3.14159;
oss << ", 文本: " << "Hello";
std::string result = oss.str();
std::cout << "格式化结果: " << result << std::endl;
}
static std::string formatMessage(const std::string& name, int age, double salary) {
std::ostringstream oss;
oss << "员工信息 - 姓名: " << name
<< ", 年龄: " << age
<< ", 薪资: $" << std::fixed << std::setprecision(2) << salary;
return oss.str();
}
};
int main() {
StringStreamDemo::inputStringStream();
StringStreamDemo::outputStringStream();
std::string info = StringStreamDemo::formatMessage("张三", 28, 5500.50);
std::cout << "\n格式化信息: " << info << std::endl;
return 0;
}📋 格式化输入输出
流格式控制
cpp
#include <iostream>
#include <iomanip>
#include <fstream>
class FormatDemo {
public:
static void numberFormatting() {
std::cout << "=== 数字格式化 ===" << std::endl;
double pi = 3.141592653589793;
int num = 42;
// 精度控制
std::cout << std::setprecision(3) << pi << std::endl;
std::cout << std::setprecision(6) << pi << std::endl;
// 固定小数点
std::cout << std::fixed << std::setprecision(2) << pi << std::endl;
// 科学记数法
std::cout << std::scientific << pi << std::endl;
// 字段宽度和对齐
std::cout << std::setw(10) << std::left << num << "|" << std::endl;
std::cout << std::setw(10) << std::right << num << "|" << std::endl;
std::cout << std::setw(10) << std::setfill('0') << num << "|" << std::endl;
// 进制输出
std::cout << "十进制: " << std::dec << num << std::endl;
std::cout << "十六进制: " << std::hex << num << std::endl;
std::cout << "八进制: " << std::oct << num << std::endl;
}
static void tableFormatting() {
std::cout << "\n=== 表格格式化 ===" << std::endl;
struct Student {
std::string name;
int age;
double gpa;
};
std::vector<Student> students = {
{"Alice", 20, 3.85},
{"Bob", 19, 3.92},
{"Charlie", 21, 3.67}
};
// 表头
std::cout << std::left << std::setw(10) << "姓名"
<< std::setw(6) << "年龄"
<< std::setw(8) << "GPA" << std::endl;
std::cout << std::string(24, '-') << std::endl;
// 表格内容
for (const auto& student : students) {
std::cout << std::left << std::setw(10) << student.name
<< std::setw(6) << student.age
<< std::fixed << std::setprecision(2) << student.gpa << std::endl;
}
}
};
int main() {
FormatDemo::numberFormatting();
FormatDemo::tableFormatting();
return 0;
}📊 二进制文件操作
二进制读写
cpp
#include <iostream>
#include <fstream>
#include <vector>
#include <cstring>
struct Person {
char name[50];
int age;
double salary;
Person() = default;
Person(const std::string& n, int a, double s) : age(a), salary(s) {
std::strncpy(name, n.c_str(), sizeof(name) - 1);
name[sizeof(name) - 1] = '\0';
}
void display() const {
std::cout << "姓名: " << name << ", 年龄: " << age
<< ", 薪资: " << salary << std::endl;
}
};
class BinaryFileHandler {
public:
static void writePersons(const std::string& filename, const std::vector<Person>& persons) {
std::ofstream file(filename, std::ios::binary);
if (!file) {
throw std::runtime_error("无法创建二进制文件");
}
for (const auto& person : persons) {
file.write(reinterpret_cast<const char*>(&person), sizeof(Person));
}
std::cout << "写入 " << persons.size() << " 个记录到 " << filename << std::endl;
}
static std::vector<Person> readPersons(const std::string& filename) {
std::ifstream file(filename, std::ios::binary);
if (!file) {
throw std::runtime_error("无法打开二进制文件");
}
std::vector<Person> persons;
Person person;
while (file.read(reinterpret_cast<char*>(&person), sizeof(Person))) {
persons.push_back(person);
}
std::cout << "从 " << filename << " 读取 " << persons.size() << " 个记录" << std::endl;
return persons;
}
};
int main() {
std::cout << "=== 二进制文件操作 ===" << std::endl;
try {
// 创建数据
std::vector<Person> persons = {
Person("张三", 25, 5000.0),
Person("李四", 30, 6000.0),
Person("王五", 28, 5500.0)
};
// 写入二进制文件
BinaryFileHandler::writePersons("persons.dat", persons);
// 读取二进制文件
auto readPersons = BinaryFileHandler::readPersons("persons.dat");
std::cout << "\n读取的数据:" << std::endl;
for (const auto& person : readPersons) {
person.display();
}
} catch (const std::exception& e) {
std::cout << "错误: " << e.what() << std::endl;
}
return 0;
}总结
C++的文件和流系统提供了灵活强大的I/O处理能力:
流类型
- ifstream: 输入文件流
- ofstream: 输出文件流
- fstream: 双向文件流
- stringstream: 字符串流
文件模式
| 模式 | 说明 | 用途 |
|---|---|---|
| ios::in | 读取模式 | 打开文件读取 |
| ios::out | 写入模式 | 打开文件写入 |
| ios::app | 追加模式 | 在文件末尾追加 |
| ios::binary | 二进制模式 | 二进制读写 |
最佳实践
- 及时关闭文件或使用RAII
- 检查文件操作状态
- 适当的异常处理
- 选择合适的文件模式
- 注意二进制和文本模式的区别
文件和流操作是C++程序与外部数据交互的重要途径。