在本章中,我们将详细探讨如何使用 C++ 处理文件和输入输出流。C++ 提供了强大的标准库支持,使得文件操作变得简单而高效。
文件流概述
文件流是 C++ 中用于读写文件的类。主要的文件流类包括 std::ifstream、std::ofstream 和 std::fstream。这些类分别用于文件的输入、输出和双向操作。
std::ifstream 类
std::ifstream 类用于从文件中读取数据。它继承自 std::istream 类。
创建文件流对象
// www.javascriptcn.com code example
#include <fstream>
#include <iostream>
int main() {
std::ifstream inputFile("example.txt"); // 打开文件
if (!inputFile) { // 检查文件是否成功打开
std::cerr << "无法打开文件" << std::endl;
return 1;
}
// 文件操作代码
}读取文件内容
// www.javascriptcn.com code example
#include <fstream>
#include <iostream>
#include <string>
int main() {
std::ifstream inputFile("example.txt");
if (!inputFile) {
std::cerr << "无法打开文件" << std::endl;
return 1;
}
std::string line;
while (getline(inputFile, line)) { // 使用 getline 函数逐行读取文件
std::cout << line << std::endl;
}
inputFile.close(); // 关闭文件
return 0;
}std::ofstream 类
std::ofstream 类用于向文件写入数据。它继承自 std::ostream 类。
创建文件流对象
// www.javascriptcn.com code example
#include <fstream>
#include <iostream>
int main() {
std::ofstream outputFile("output.txt"); // 创建并打开文件
if (!outputFile) { // 检查文件是否成功创建
std::cerr << "无法创建文件" << std::endl;
return 1;
}
// 文件操作代码
}向文件写入数据
// www.javascriptcn.com code example
#include <fstream>
#include <iostream>
int main() {
std::ofstream outputFile("output.txt");
if (!outputFile) {
std::cerr << "无法创建文件" << std::endl;
return 1;
}
outputFile << "Hello, World!" << std::endl; // 向文件写入字符串
outputFile << 123 << std::endl; // 向文件写入整数
outputFile.close(); // 关闭文件
return 0;
}std::fstream 类
std::fstream 类用于同时进行文件的读写操作。它继承自 std::iostream 类。
创建文件流对象
// www.javascriptcn.com code example
#include <fstream>
#include <iostream>
int main() {
std::fstream fileStream("example.txt", std::ios::in | std::ios::out); // 打开文件进行读写
if (!fileStream) {
std::cerr << "无法打开文件" << std::endl;
return 1;
}
// 文件操作代码
}文件的读写操作
// www.javascriptcn.com code example
#include <fstream>
#include <iostream>
int main() {
std::fstream fileStream("example.txt", std::ios::in | std::ios::out);
if (!fileStream) {
std::cerr << "无法打开文件" << std::endl;
return 1;
}
std::string content;
fileStream.seekg(0, std::ios::end); // 移动到文件末尾
int length = fileStream.tellg(); // 获取文件长度
fileStream.seekg(0, std::ios::beg); // 移动到文件开头
content.resize(length); // 分配足够的空间来存储文件内容
fileStream.read(&content[0], length); // 读取文件内容
std::cout << "文件内容:" << std::endl;
std::cout << content << std::endl;
fileStream.clear(); // 清除状态标志
fileStream.seekp(0, std::ios::end); // 移动到文件末尾
fileStream << "\n附加的内容"; // 向文件末尾追加内容
fileStream.close();
return 0;
}文件流操作符重载
C++ 的文件流类提供了许多操作符重载,使得文件操作更加方便。
读取和写入基本类型
文件流可以自动处理基本类型的读写操作,如整型、浮点型等。
// www.javascriptcn.com code example
#include <fstream>
#include <iostream>
int main() {
std::ofstream outputFile("numbers.txt");
if (!outputFile) {
std::cerr << "无法创建文件" << std::endl;
return 1;
}
int number = 42;
outputFile << number << std::endl; // 写入整数
double value = 3.14;
outputFile << value << std::endl; // 写入浮点数
outputFile.close();
std::ifstream inputFile("numbers.txt");
if (!inputFile) {
std::cerr << "无法打开文件" << std::endl;
return 1;
}
int readNumber;
inputFile >> readNumber; // 读取整数
std::cout << "读取的整数: " << readNumber << std::endl;
double readValue;
inputFile >> readValue; // 读取浮点数
std::cout << "读取的浮点数: " << readValue << std::endl;
inputFile.close();
return 0;
}使用 getline 读取字符串
getline 函数可以从文件流中读取一行文本,并将其存储在一个字符串变量中。
// www.javascriptcn.com code example
#include <fstream>
#include <iostream>
#include <string>
int main() {
std::ofstream outputFile("text.txt");
if (!outputFile) {
std::cerr << "无法创建文件" << std::endl;
return 1;
}
outputFile << "Hello, C++" << std::endl;
outputFile << "Welcome to File I/O" << std::endl;
outputFile.close();
std::ifstream inputFile("text.txt");
if (!inputFile) {
std::cerr << "无法打开文件" << std::endl;
return 1;
}
std::string line;
while (getline(inputFile, line)) {
std::cout << line << std::endl;
}
inputFile.close();
return 0;
}文件模式
C++ 文件流提供了多种打开文件的模式,通过组合这些模式,可以灵活地控制文件的操作行为。
文件打开模式
std::ios::in: 仅用于读取。std::ios::out: 仅用于写入。std::ios::app: 在文件末尾追加内容。std::ios::ate: 打开文件后立即定位到文件末尾。std::ios::trunc: 如果文件已存在,则删除其内容。std::ios::binary: 以二进制模式打开文件。
示例:组合模式
// www.javascriptcn.com code example
#include <fstream>
#include <iostream>
int main() {
std::ofstream outputFile("log.txt", std::ios::out | std::ios::app); // 以追加模式打开文件
if (!outputFile) {
std::cerr << "无法创建文件" << std::endl;
return 1;
}
outputFile << "新的日志条目" << std::endl;
outputFile.close();
return 0;
}错误处理
文件操作可能由于各种原因失败,因此需要妥善处理错误情况。
检查文件打开状态
可以通过检查文件流的状态标志来判断文件操作是否成功。
// www.javascriptcn.com code example
#include <fstream>
#include <iostream>
int main() {
std::ifstream inputFile("missing.txt");
if (!inputFile) {
std::cerr << "文件打开失败" << std::endl;
return 1;
}
std::string line;
while (getline(inputFile, line)) {
std::cout << line << std::endl;
}
inputFile.close();
return 0;
}清除状态标志
在某些情况下,可能需要清除文件流的状态标志,以便继续操作。
// www.javascriptcn.com code example
#include <fstream>
#include <iostream>
int main() {
std::fstream fileStream("example.txt", std::ios::in | std::ios::out);
if (!fileStream) {
std::cerr << "无法打开文件" << std::endl;
return 1;
}
fileStream << "Hello, World!" << std::endl;
fileStream.clear(); // 清除状态标志
fileStream.seekg(0, std::ios::beg); // 移动到文件开头
std::string content;
while (getline(fileStream, content)) {
std::cout << content << std::endl;
}
fileStream.close();
return 0;
}文件缓冲
C++ 文件流默认使用缓冲机制,以提高性能。可以手动控制缓冲行为,例如刷新缓冲区。
刷新缓冲区
// www.javascriptcn.com code example
#include <fstream>
#include <iostream>
int main() {
std::ofstream outputFile("output.txt");
if (!outputFile) {
std::cerr << "无法创建文件" << std::endl;
return 1;
}
outputFile << "第一行" << std::endl;
outputFile.flush(); // 刷新缓冲区
outputFile << "第二行" << std::endl;
outputFile.close();
return 0;
}禁用缓冲
可以通过设置文件流为无缓冲模式来禁用缓冲。
// www.javascriptcn.com code example
#include <fstream>
#include <iostream>
int main() {
std::ofstream outputFile("output.txt", std::ios::out | std::ios::binary);
if (!outputFile) {
std::cerr << "无法创建文件" << std::endl;
return 1;
}
outputFile.rdbuf()->pubsetbuf(nullptr, 0); // 禁用缓冲
outputFile << "无缓冲模式下的数据" << std::endl;
outputFile.close();
return 0;
}总结
本章介绍了 C++ 中文件和流的基本概念及操作方法。通过学习这些内容,你将能够有效地处理文件输入输出任务,从而增强你的程序功能。下一部分我们将探讨更高级的文件操作技术,包括内存映射文件和多线程文件访问等主题。