### 文章目录
- [@[toc]](#文章目录 @[toc] Day5-2 文件IO(2025.03.24) 1. 缓冲区与刷新 1.1 常见的缓冲刷新方式 2. 文件读写操作 2.1 读取文件 2.2 写入文件 2.3 追加模式写入 2.3 完整代码 3. 文件定位操作 4. 字符串IO 5. 配置文件解析示例 6. 完整代码 7. 二进制文件操作 总结)
- [Day5-2 文件IO(2025.03.24)](#文章目录 @[toc] Day5-2 文件IO(2025.03.24) 1. 缓冲区与刷新 1.1 常见的缓冲刷新方式 2. 文件读写操作 2.1 读取文件 2.2 写入文件 2.3 追加模式写入 2.3 完整代码 3. 文件定位操作 4. 字符串IO 5. 配置文件解析示例 6. 完整代码 7. 二进制文件操作 总结)
- [1. 缓冲区与刷新](#文章目录 @[toc] Day5-2 文件IO(2025.03.24) 1. 缓冲区与刷新 1.1 常见的缓冲刷新方式 2. 文件读写操作 2.1 读取文件 2.2 写入文件 2.3 追加模式写入 2.3 完整代码 3. 文件定位操作 4. 字符串IO 5. 配置文件解析示例 6. 完整代码 7. 二进制文件操作 总结)
- [1.1 常见的缓冲刷新方式](#文章目录 @[toc] Day5-2 文件IO(2025.03.24) 1. 缓冲区与刷新 1.1 常见的缓冲刷新方式 2. 文件读写操作 2.1 读取文件 2.2 写入文件 2.3 追加模式写入 2.3 完整代码 3. 文件定位操作 4. 字符串IO 5. 配置文件解析示例 6. 完整代码 7. 二进制文件操作 总结)
- [2. 文件读写操作](#文章目录 @[toc] Day5-2 文件IO(2025.03.24) 1. 缓冲区与刷新 1.1 常见的缓冲刷新方式 2. 文件读写操作 2.1 读取文件 2.2 写入文件 2.3 追加模式写入 2.3 完整代码 3. 文件定位操作 4. 字符串IO 5. 配置文件解析示例 6. 完整代码 7. 二进制文件操作 总结)
- [2.1 读取文件](#文章目录 @[toc] Day5-2 文件IO(2025.03.24) 1. 缓冲区与刷新 1.1 常见的缓冲刷新方式 2. 文件读写操作 2.1 读取文件 2.2 写入文件 2.3 追加模式写入 2.3 完整代码 3. 文件定位操作 4. 字符串IO 5. 配置文件解析示例 6. 完整代码 7. 二进制文件操作 总结)
- [2.2 写入文件](#文章目录 @[toc] Day5-2 文件IO(2025.03.24) 1. 缓冲区与刷新 1.1 常见的缓冲刷新方式 2. 文件读写操作 2.1 读取文件 2.2 写入文件 2.3 追加模式写入 2.3 完整代码 3. 文件定位操作 4. 字符串IO 5. 配置文件解析示例 6. 完整代码 7. 二进制文件操作 总结)
- [2.3 追加模式写入](#文章目录 @[toc] Day5-2 文件IO(2025.03.24) 1. 缓冲区与刷新 1.1 常见的缓冲刷新方式 2. 文件读写操作 2.1 读取文件 2.2 写入文件 2.3 追加模式写入 2.3 完整代码 3. 文件定位操作 4. 字符串IO 5. 配置文件解析示例 6. 完整代码 7. 二进制文件操作 总结)
- [2.3 完整代码](#文章目录 @[toc] Day5-2 文件IO(2025.03.24) 1. 缓冲区与刷新 1.1 常见的缓冲刷新方式 2. 文件读写操作 2.1 读取文件 2.2 写入文件 2.3 追加模式写入 2.3 完整代码 3. 文件定位操作 4. 字符串IO 5. 配置文件解析示例 6. 完整代码 7. 二进制文件操作 总结)
- [3. 文件定位操作](#文章目录 @[toc] Day5-2 文件IO(2025.03.24) 1. 缓冲区与刷新 1.1 常见的缓冲刷新方式 2. 文件读写操作 2.1 读取文件 2.2 写入文件 2.3 追加模式写入 2.3 完整代码 3. 文件定位操作 4. 字符串IO 5. 配置文件解析示例 6. 完整代码 7. 二进制文件操作 总结)
- [4. 字符串IO](#文章目录 @[toc] Day5-2 文件IO(2025.03.24) 1. 缓冲区与刷新 1.1 常见的缓冲刷新方式 2. 文件读写操作 2.1 读取文件 2.2 写入文件 2.3 追加模式写入 2.3 完整代码 3. 文件定位操作 4. 字符串IO 5. 配置文件解析示例 6. 完整代码 7. 二进制文件操作 总结)
- [5. 配置文件解析示例](#文章目录 @[toc] Day5-2 文件IO(2025.03.24) 1. 缓冲区与刷新 1.1 常见的缓冲刷新方式 2. 文件读写操作 2.1 读取文件 2.2 写入文件 2.3 追加模式写入 2.3 完整代码 3. 文件定位操作 4. 字符串IO 5. 配置文件解析示例 6. 完整代码 7. 二进制文件操作 总结)
- [6. 完整代码](#文章目录 @[toc] Day5-2 文件IO(2025.03.24) 1. 缓冲区与刷新 1.1 常见的缓冲刷新方式 2. 文件读写操作 2.1 读取文件 2.2 写入文件 2.3 追加模式写入 2.3 完整代码 3. 文件定位操作 4. 字符串IO 5. 配置文件解析示例 6. 完整代码 7. 二进制文件操作 总结)
- [7. 二进制文件操作](#文章目录 @[toc] Day5-2 文件IO(2025.03.24) 1. 缓冲区与刷新 1.1 常见的缓冲刷新方式 2. 文件读写操作 2.1 读取文件 2.2 写入文件 2.3 追加模式写入 2.3 完整代码 3. 文件定位操作 4. 字符串IO 5. 配置文件解析示例 6. 完整代码 7. 二进制文件操作 总结)
- [总结](#文章目录 @[toc] Day5-2 文件IO(2025.03.24) 1. 缓冲区与刷新 1.1 常见的缓冲刷新方式 2. 文件读写操作 2.1 读取文件 2.2 写入文件 2.3 追加模式写入 2.3 完整代码 3. 文件定位操作 4. 字符串IO 5. 配置文件解析示例 6. 完整代码 7. 二进制文件操作 总结)
Day5-2 文件IO(2025.03.24)
1. 缓冲区与刷新
在C++的标准输入输出流 (iostream
) 中,I/O 操作通常会涉及缓冲区,以提高效率。默认情况下,cout
采用缓冲模式,输出内容会暂存到缓冲区,只有在缓冲区满了或遇到某些特殊情况(如换行)时,数据才会被刷新到屏幕。
1.1 常见的缓冲刷新方式
方法 | 作用 | 例子 |
---|---|---|
cout << endl; |
输出换行并刷新缓冲区 | cout << "Hello" << endl; |
cout << flush; |
只刷新缓冲区,但不换行 | cout << "Hello" << flush; |
cout << ends; |
在缓冲区加入一个空字符(\0 ),但不会刷新 |
cout << "Hello" << ends; |
cpp
#include <iostream>
#include <thread>
#include <chrono>
using namespace std;
void test()
{
for (size_t i = 0; i < 1024; i++)
{
cout << "a";
}
cout << 'b' << endl; // 刷新缓冲区并换行
cout << "c" << flush; // 只刷新,不换行
cout << "d" << ends; // 只插入空字符,不刷新
this_thread::sleep_for(chrono::seconds(5));
}
int main()
{
test();
return 0;
}
2. 文件读写操作
C++标准库提供了 <fstream>
头文件,其中包含三个主要的文件流类:
类名 | 作用 |
---|---|
ifstream |
读文件(input file stream) |
ofstream |
写文件(output file stream) |
fstream |
读写文件(file stream) |
2.1 读取文件
cpp
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
void readFile()
{
ifstream ifs("test.txt"); // 打开文件
if (!ifs.is_open())
{
cerr << "文件打开失败" << endl;
return;
}
string line;
while (getline(ifs, line))
{
cout << line << endl;
}
ifs.close(); // 关闭文件
}
int main()
{
readFile();
return 0;
}
2.2 写入文件
cpp
void writeFile()
{
ofstream ofs("output.txt");
if (!ofs)
{
cerr << "文件打开失败" << endl;
return;
}
ofs << "Hello, world!" << endl;
ofs.close();
}
2.3 追加模式写入
使用 ios::app
选项可以在文件末尾追加内容,而不会覆盖原有数据。
cpp
void appendToFile()
{
ofstream ofs("log.txt", ios::app);
if (!ofs)
{
cerr << "文件打开失败" << endl;
return;
}
ofs << "新日志记录" << endl;
ofs.close();
}
2.3 完整代码
cpp
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;
void test()
{
ifstream ifs("test.txt");
if (!ifs.good())
{
cout << "文件打开失败" << endl;
return;
}
//文件流读文件
//对于文件输入流而言,默认以空格作为分隔符
string line;
while (ifs >> line)//cin >> line
{
cout << line << endl;
}
}
void test2()
{
ifstream ifs("test.txt");
if (!ifs.good())
{
cout << "文件打开失败" << endl;
return;
}
//文件流读文件
//对于文件输入流而言,默认以空格作为分隔符
string line;
while (getline(ifs,line))
{
cout << line << endl;
}
}
//打印前几行的内容
void test3()
{
ifstream ifs("test.txt");
if (!ifs.good())
{
cout << "文件打开失败" << endl;
return;
}
//文件流读文件
//对于文件输入流而言,默认以空格作为分隔符
string line;
int lineNum = 0;
while (getline(ifs, line))
{
cout << line << endl;
lineNum++;
if (lineNum == 5)
{
break;
}
}
}
//打印指定行的内容
void test4()
{
string fileName = "test.txt";
ifstream ifs(fileName);
if (!ifs.good())
{
cout << "文件打开失败" << endl;
return;
}
//文件流读文件
//对于文件输入流而言,默认以空格作为分隔符
string line[120];
size_t lineNum = 0;
vector<string> vec;
while (getline(ifs, line[lineNum]))
{
++lineNum;
}
cout << "line[22] = " << line[22] << endl;
}
void test5()
{
string fileName = "test.txt";
ifstream ifs(fileName);
if (!ifs.good())
{
cout << "文件打开失败" << endl;
return;
}
//文件流读文件
//对于文件输入流而言,默认以空格作为分隔符
string line;
vector<string> vec;
while (getline(ifs, line))
{
vec.push_back(line);
}
cout << "vec[22] = " << vec[22] << endl;
}
void test6()
{
ifstream ifs("test.txt");
if (!ifs.good())
{
cerr << "ifstream is not good!" << endl;
return;
}
ofstream ofs("wd.txt");
if (!ofs.good())
{
cerr << "ofstream is not good!" << endl;
ifs.close();//在程序异常退出时,关闭前面的ifs
return;
}
string line;
while (getline(ifs, line))
{
ofs << line << endl;
}
ifs.close();
ofs.close();
}
void test7()
{
//对于文件的输出输出流而言,当文件不存在的时候就打开失败
fstream fs("wenchang.txt");
if (!fs.good())
{
cerr << "fstream is not good!" << endl;
return;
}
//业务逻辑
//通过键盘输入数据,使用fs进行读文件,随后输出到屏幕
int number = 0;
cout << "请输入5次数字: " << endl;
for (size_t idx = 0; idx != 5; ++idx)
{
cin >> number;
fs << number << " ";
}
size_t len = fs.tellp();
cout << "len= " << len << endl;
fs.seekp(0);
len = fs.tellp();
cout << "len= " << len << endl;
for (size_t idx = 0; idx != 5; ++idx)
{
cout << "fs.failbit = " << fs.fail() << endl
<< "fs.eofbit = " << fs.eof() << endl
<< "fs.goodbit = " << fs.good() << endl;
fs >> number;
cout << number << " ";
}
cout << endl;
fs.close();
}
//追加模式
void test8()
{
ifstream ifs("test.txt", std::ios::in | std::ios::ate);
if (!ifs.good())
{
cerr << "ifstream is not good!" << endl;
return;
}
cout << "ifs.tellg() = " << ifs.tellg() << endl;
ifs.close();
}
void test9()
{
ofstream ofs("wenchang.txt",std::ios::out | std::ios::app);
if (!ofs.good())
{
cerr << "ofstream is not good!" << endl;
return;
}
cout << "ofs.tellg() = " << ofs.tellp() << endl;
ofs.close();
}
int main(int argc, char* argv[])
{
//test();
//test5(); //读取文件内容到vector容器中
test9();
return 0;
}
3. 文件定位操作
文件流支持 seekg()
(get)和 seekp()
(put)来定位文件指针。
cpp
void filePositioning()
{
fstream fs("test.txt", ios::in | ios::out);
if (!fs)
{
cerr << "文件打开失败" << endl;
return;
}
fs.seekg(0, ios::end); // 移动到文件末尾
cout << "文件大小: " << fs.tellg() << " 字节" << endl;
fs.close();
}
4. 字符串IO
C++ 提供了 stringstream
以便在字符串中进行 I/O 操作。
cpp
#include <sstream>
void stringStreamDemo()
{
stringstream ss;
int num = 42;
ss << "数字: " << num;
string output = ss.str();
cout << output << endl;
}
5. 配置文件解析示例
cpp
void readConfig(const string& filename)
{
ifstream ifs(filename);
if (!ifs)
{
cerr << "打开文件失败: " << filename << endl;
return;
}
string line;
while (getline(ifs, line))
{
istringstream iss(line);
string key, value;
iss >> key >> value;
cout << key << " -> " << value << endl;
}
ifs.close();
}
6. 完整代码
cpp
#include <iostream>
#include <sstream>
#include <fstream> // 添加此行以包含 ifstream 的定义
using namespace std;
using std::ostringstream;
using std::istringstream;
using std::stringstream;
string int2string(int value)
{
ostringstream oss;//中转
oss << value;
return oss.str();//获取底层的字符串
}
void test()
{
int number = 10;
string s1 = int2string(number);
cout << "s1 = " << s1 << endl;
}
void test2()
{
int number1 = 10;
int number2 = 20;
stringstream ss;
ss << "number1 = " << number1
<< "number2 = " << number2;
string s1 = ss.str();
cout << "s1 =" << s1 << endl;
string key;
string value;
while (ss >> key >> value)
{
cout << key << "--->" << value << endl;
}
}
void readConfig(const string& filename)
{
ifstream ifs(filename);
if (!ifs)
{
cerr << "open" << filename << "error!" << endl;
return;
}
string line;
while (getline(ifs, line))
{
istringstream iss(line);
string key, value;
iss >> key >> value;
cout << key << " " << value << endl;
}
ifs.close();
}
void test3()
{
readConfig("my.conf");
}
int main()
{
test3();
return 0;
}
7. 二进制文件操作
cpp
#include <iostream>
#include <fstream>
using namespace std;
struct Data {
int id;
double value;
};
// 写入二进制文件
void writeBinaryFile(const string &filename)
{
ofstream ofs(filename, ios::binary);
if (!ofs)
{
cerr << "文件打开失败!" << endl;
return;
}
Data d = {1, 3.14};
ofs.write(reinterpret_cast<const char *>(&d), sizeof(d));
ofs.close();
}
// 读取二进制文件
void readBinaryFile(const string &filename)
{
ifstream ifs(filename, ios::binary);
if (!ifs)
{
cerr << "文件打开失败!" << endl;
return;
}
Data d;
ifs.read(reinterpret_cast<char *>(&d), sizeof(d));
cout << "id: " << d.id << ", value: " << d.value << endl;
ifs.close();
}
int main()
{
string filename = "data.bin";
writeBinaryFile(filename);
readBinaryFile(filename);
return 0;
}
总结
- 文本文件
ifstream
读取文件,ofstream
写入文件,fstream
读写文件。seekg()
和seekp()
控制文件指针。stringstream
适用于字符串的 I/O 操作。ios::app
可用于追加模式写入文件。
- 二进制文件
- 读写方式:
ifstream
、ofstream
需使用ios::binary
模式 - 读取方式:
read()
和write()
- 适用于存储结构化数据,如
struct
类型的存储和读取。
- 读写方式: