C++ 学习计划 - 第三周第21天:文件操作与IO
第21天:文件操作与IO
学习目标
掌握C++的文件操作和IO流,理解文本文件与二进制文件的处理,学会使用字符串流和错误处理。
核心知识点
1. 文件流概述
C++提供了多种文件流类来处理文件操作:
ifstream
:输入文件流(读取文件)
ofstream
:输出文件流(写入文件)
fstream
:文件流(读写文件)
头文件包含
1 2 3
| #include <fstream> #include <iostream> #include <sstream>
|
参考资料
2. 基本文件操作
文件写入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| #include <fstream> #include <iostream> #include <string>
void fileWritingExample() { std::ofstream outFile("example.txt"); if (outFile.is_open()) { outFile << "Hello, World!" << std::endl; outFile << "This is a test file." << std::endl; outFile << "Line 3" << std::endl; int number = 42; outFile << "Number: " << number << std::endl; outFile.close(); std::cout << "文件写入成功" << std::endl; } else { std::cout << "无法打开文件" << std::endl; } }
|
文件读取
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| void fileReadingExample() { std::ifstream inFile("example.txt"); if (inFile.is_open()) { std::string line; while (std::getline(inFile, line)) { std::cout << "读取: " << line << std::endl; } inFile.close(); } else { std::cout << "无法打开文件" << std::endl; } }
|
文件读写
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| void fileReadWriteExample() { std::fstream file("data.txt", std::ios::in | std::ios::out | std::ios::trunc); if (file.is_open()) { file << "Line 1" << std::endl; file << "Line 2" << std::endl; file << "Line 3" << std::endl; file.seekg(0, std::ios::beg); std::string line; while (std::getline(file, line)) { std::cout << "读取: " << line << std::endl; } file.close(); } else { std::cout << "无法打开文件" << std::endl; } }
|
参考资料
3. 文件模式
常用文件模式
1 2 3 4 5 6 7 8 9
| std::ofstream out1("file1.txt", std::ios::out); std::ofstream out2("file2.txt", std::ios::out | std::ios::app); std::ofstream out3("file3.txt", std::ios::out | std::ios::trunc);
std::ifstream in1("file1.txt", std::ios::in); std::ifstream in2("file1.txt", std::ios::in | std::ios::binary);
std::fstream file("file4.txt", std::ios::in | std::ios::out | std::ios::app);
|
文件模式说明
std::ios::in
:读取模式
std::ios::out
:写入模式
std::ios::app
:追加模式
std::ios::trunc
:截断模式(清空文件)
std::ios::binary
:二进制模式
std::ios::ate
:打开时定位到文件末尾
参考资料
4. 二进制文件操作
二进制写入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| #include <vector>
struct Person { char name[50]; int age; double salary; };
void binaryWritingExample() { std::ofstream outFile("people.bin", std::ios::binary); if (outFile.is_open()) { Person people[] = { {"Alice", 25, 50000.0}, {"Bob", 30, 60000.0}, {"Charlie", 35, 70000.0} }; outFile.write(reinterpret_cast<const char*>(people), sizeof(people)); outFile.close(); std::cout << "二进制文件写入成功" << std::endl; } else { std::cout << "无法打开文件" << std::endl; } }
|
二进制读取
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| void binaryReadingExample() { std::ifstream inFile("people.bin", std::ios::binary); if (inFile.is_open()) { inFile.seekg(0, std::ios::end); size_t fileSize = inFile.tellg(); inFile.seekg(0, std::ios::beg); size_t numRecords = fileSize / sizeof(Person); std::vector<Person> people(numRecords); inFile.read(reinterpret_cast<char*>(people.data()), fileSize); for (const auto& person : people) { std::cout << "姓名: " << person.name << ", 年龄: " << person.age << ", 工资: " << person.salary << std::endl; } inFile.close(); } else { std::cout << "无法打开文件" << std::endl; } }
|
参考资料
5. 文件定位
文件指针操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| void filePositioningExample() { std::fstream file("position.txt", std::ios::in | std::ios::out | std::ios::trunc); if (file.is_open()) { file << "Line 1: Hello" << std::endl; file << "Line 2: World" << std::endl; file << "Line 3: C++" << std::endl; file << "Line 4: Programming" << std::endl; std::cout << "当前位置: " << file.tellg() << std::endl; file.seekg(0, std::ios::beg); std::cout << "移动到开头后位置: " << file.tellg() << std::endl; file.seekg(0, std::ios::end); std::cout << "移动到末尾后位置: " << file.tellg() << std::endl; file.seekg(10, std::ios::beg); std::cout << "移动到位置10后位置: " << file.tellg() << std::endl; file.seekg(-5, std::ios::cur); std::cout << "向前移动5个位置后位置: " << file.tellg() << std::endl; file.close(); } }
|
定位函数说明
tellg()
:获取读指针位置
tellp()
:获取写指针位置
seekg(pos)
:设置读指针位置
seekp(pos)
:设置写指针位置
seekg(offset, dir)
:相对定位
参考资料
6. 字符串流
std::stringstream
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| #include <sstream>
void stringStreamExample() { std::string str = "123 456 789"; std::stringstream ss(str); int num1, num2, num3; ss >> num1 >> num2 >> num3; std::cout << "数字1: " << num1 << std::endl; std::cout << "数字2: " << num2 << std::endl; std::cout << "数字3: " << num3 << std::endl; std::stringstream ss2; int value = 42; double pi = 3.14159; ss2 << "Value: " << value << ", Pi: " << pi; std::string result = ss2.str(); std::cout << "结果: " << result << std::endl; }
|
std::istringstream 和 std::ostringstream
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| void specializedStringStreamExample() { std::string input = "Hello World 123 45.67"; std::istringstream iss(input); std::string word1, word2; int number; double decimal; iss >> word1 >> word2 >> number >> decimal; std::cout << "单词1: " << word1 << std::endl; std::cout << "单词2: " << word2 << std::endl; std::cout << "数字: " << number << std::endl; std::cout << "小数: " << decimal << std::endl; std::ostringstream oss; oss << "结果: " << word1 << " " << word2 << " " << number << " " << decimal; std::string output = oss.str(); std::cout << "输出: " << output << std::endl; }
|
参考资料
7. 错误处理
文件状态检查
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| void errorHandlingExample() { std::ifstream file("nonexistent.txt"); if (!file.is_open()) { std::cout << "错误: 无法打开文件" << std::endl; return; } if (file.fail()) { std::cout << "错误: 文件操作失败" << std::endl; return; } if (file.bad()) { std::cout << "错误: 文件流损坏" << std::endl; return; } if (file.eof()) { std::cout << "警告: 已到达文件末尾" << std::endl; } file.clear(); file.close(); }
|
异常处理
1 2 3 4 5 6 7 8 9 10 11 12 13
| void exceptionHandlingExample() { try { std::ifstream file("data.txt"); file.exceptions(std::ifstream::failbit | std::ifstream::badbit); std::string line; while (std::getline(file, line)) { std::cout << line << std::endl; } } catch (const std::ifstream::failure& e) { std::cout << "文件操作异常: " << e.what() << std::endl; } }
|
参考资料
8. 文件管理器类
实用文件操作工具
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
| #include <filesystem>
class FileManager { public: static bool copyFile(const std::string& source, const std::string& destination) { std::ifstream src(source, std::ios::binary); std::ofstream dst(destination, std::ios::binary); if (!src.is_open() || !dst.is_open()) { return false; } dst << src.rdbuf(); return true; } static bool moveFile(const std::string& source, const std::string& destination) { if (copyFile(source, destination)) { return std::remove(source.c_str()) == 0; } return false; } static std::vector<std::string> readLines(const std::string& filename) { std::vector<std::string> lines; std::ifstream file(filename); if (file.is_open()) { std::string line; while (std::getline(file, line)) { lines.push_back(line); } file.close(); } return lines; } static void writeLines(const std::string& filename, const std::vector<std::string>& lines) { std::ofstream file(filename); if (file.is_open()) { for (const auto& line : lines) { file << line << std::endl; } file.close(); } } static size_t getFileSize(const std::string& filename) { std::ifstream file(filename, std::ios::binary | std::ios::ate); if (file.is_open()) { return file.tellg(); } return 0; } static bool fileExists(const std::string& filename) { std::ifstream file(filename); return file.good(); } static bool fileExistsModern(const std::string& filename) { return std::filesystem::exists(filename); } static size_t getFileSizeModern(const std::string& filename) { return std::filesystem::file_size(filename); } };
|
参考资料
9. 高级IO操作
格式化输出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| #include <iomanip>
void formattedOutputExample() { std::ofstream file("formatted.txt"); if (file.is_open()) { double pi = 3.14159265359; int number = 42; file << std::fixed << std::setprecision(2) << pi << std::endl; file << std::setw(10) << std::left << "Name" << std::setw(5) << std::right << "Age" << std::endl; file << std::setw(10) << std::left << "Alice" << std::setw(5) << std::right << 25 << std::endl; file << "Hex: " << std::hex << number << std::endl; file.close(); } }
|
自定义分隔符
1 2 3 4 5 6 7 8 9 10
| void customDelimiterExample() { std::string data = "apple,banana,cherry,date"; std::stringstream ss(data); std::string item; while (std::getline(ss, item, ',')) { std::cout << "Item: " << item << std::endl; } }
|
参考资料
实用教程和文档
官方文档
优质教程
实战案例
今日练习
基础练习
- 实现一个日志系统,支持不同级别的日志记录
- 编写一个配置文件解析器,支持键值对格式
- 实现一个数据序列化系统,支持二进制和文本格式
算法题推荐
- LeetCode 68. Text Justification - 文本对齐,涉及字符串处理
- LeetCode 151. Reverse Words in a String - 字符串处理
- LeetCode 165. Compare Version Numbers - 版本号比较
- LeetCode 273. Integer to English Words - 数字转英文单词
学习要点总结
- 文件流类型:掌握ifstream、ofstream、fstream的使用
- 文件模式:理解不同的文件打开模式
- 二进制操作:学会处理二进制文件
- 字符串流:掌握stringstream的使用
- 错误处理:学会处理文件操作错误
第三周总结
经过第三周的学习,你已经掌握了:
- STL容器:vector、list、map等容器的使用
- STL算法:查找、排序、修改等算法的应用
- 智能指针:现代C++的内存管理技术
- Lambda表达式:函数式编程的基础
- 移动语义:性能优化的重要技术
- 并发编程:多线程和异步编程基础
- 文件IO:文件操作和流处理技术
这些都是现代C++开发中的核心技术,为你进入第四周的高级主题和项目实战打下了坚实基础。
上一天:并发编程基础 | 返回第三周总览 | 下一周:高级主题与实战