下面介绍C++中的iostream、fstream、sstream的使用方法,内容出自C++primer第八章内容。
一、 IO类
1.三种IO类型
加w的类型为对宽字符wchar_t的操作,如wistream、wostream中的wcin、wcot、werror。
ifstream和isteingstream都继承自istream,可使用cin的功能(如>>和getline等)。ofstream和ostringstream都继承自ostream,可使用cout的功能
2.不能拷贝或对IO对象赋值:
不能将形参后返回值设置为流类型,通常以引用方式传递和返回流进行IO操作,并且返回的引用不能为const,因为读写IO会改变其状态。
3.条件状态
IO类定义的函数和标志,便于访问和控制流条件状态。
IO流读写错误时(比如期望输入int,结果输入了字符或文件结束标志),后续IO操作都会失败。为保证流对象的状态正确,一般将它当作条件使用,如果输入成功,流保持有效状态,条件为真。
while(cin>>word)
可通过上面表中的函数查询标志位状态,如操作good在所有错误位未置位情况下返回true,而bad\fail\eof则在对应错误位置置位时返回true。
无参数clear可以清除所有错误标志位,执行后调用good会返回true。带参数clear接收iostate值,表示流的新状态,可以通过该功能复位指定状态位。
3.管理输出缓冲
每个输出流都管理一个缓冲区用来保存程序读写的数据,系统可将多个输出组合为单一的设备写操作以提升性能。导致缓冲刷新(数据真正写入设备或文件)包括:程序正常结束、缓冲区满、endl、unitbuf、一个输出流可能被关联到另一个流。如果程序异常终止,输出缓冲区不会被刷新。
二、 文件输入输出
通过定义文件流对象可将对象和文件关联起来,通过open成员函数定位给定文件并打开为读或写模式,也可在创建文件流对象提供文件名,然后open会被自动调用。
ofstream out1;
out1.open("filename.txt", ios::in | ios::binary);//打开文件方法1
//ofstream out("filename.txt");//打开文件方法2 在构造函数直接调用了open函数
通常需要对open是否成功进行检测:if (out1.is_open())。
在要求使用基类对象的地方可使用继承类型对象替代,iostream类型引用或指针的参数可用fstream后sstream类型调用。
Ifstream关联文件默认in模式,ofstream关联文件默认out模式,fstream关联文件默认in和out模式。
(删除文件:将文件的目录项删掉并释放磁盘块,截断文件:将文件中的部位数据删掉 不删除目录项 )
三、 String流
istringstream从string中读取数据,ostringstream向string中写入数据,头文件stringstream既可读又可写string数据。Sstream也继承了iostrea,还增加了下面的操作:
anmy 2345 56437
daga 23456 67543
hsagg 26789 8765
定义简单地类描述输入数据:
struct PersonInfo{
string name;
vector phones;
};
程序会读取数据文件并创建PersonInfo的vector,,vector中每个元素对应文件中的一条记录,在循环中处理输入输出,每个循环读取一条记录。如下所示。
string line, word;
vector<PersonInfo> people;
while (getline(cin,line)){
PersonInfo info;
istringstream record(line);
record >> info.name;
while (record >> word){
info.phones.push_back(word);
}
people.push_back(info);
}
通过getline从标准输入读取整条记录,如果调用成功,line中将保存着从输入文件而来的一条记录。在循环中定义了局部PersonInfo对象保存当前记录,接下来将istringstream和刚刚读取的文本绑定,然后通过运算符记录当前中的每个元素。
2. ostringstream
当逐步构造输出,希望最后一起打印时,采用ostringstream很有用。比如对上面的例子只输出有效的电话号码。对无效的号码不会将它们输出到新文件中,而是打印一条包含人名和无效号码的错误信息。
for (const auto &entry : people) {
ostringstream formatted, badNums;
for (const auto &nums : entry.phones){
if (strcmp(nums.c_str(), "8766") < 0)
badNums << "bad " << nums;
else {
formatted << "ok " << nums;
}
}
if (badNums.str().empty())
cout << entry.name << " " << formatted.str() << endl;
else
cerr << "input error:" << entry.name << "invalid number " << badNums.str() << endl;
}
#include
#include
#include
#include
using namespace std;
const char * filename = "test.txt";
struct PersonInfo{
string name;
vector<string> phones;
};
int main() {
char buffer[1024];
/***************************文本文件读写*******************************/
ofstream out1;
out1.open("test.txt");//ofstream默认情况或不指定app模式下打开文件会导致文件内容丢失
out1.open(filename, ios::out | ios::app);//打开文件方法1,指定app模式
ofstream out1("test.txt", ios::out | ios::app);//打开文件方法2 在构造函数直接调用了open函数
if (out1.is_open()) {
out1 << "hi!\n";
out1.close();
}
else
cout << "error opening file";
ifstream in(filename, ios::in);
if (!in.is_open()) {
cout << "error opening file"; exit(1);
}
while (!in.eof()) {
in.getline(buffer,20);//getline 第二个参数不能比实际行数小
cout << buffer << endl;
}
//in.close();////当指针直到eof后,若要重置指针位置到开头,需要采用下面两种方法
//in.open("test.txt", ios::in);//方法1:要重新打开文件后才能将指针重定位到开始位置
in.clear(); //方法2:对流状态标志进行清除
long length1, length2;
in.seekg(0, ios::beg);
length1 = in.tellg();
in.seekg(0,ios::end);//将get指针移动到beg文件结束位置
length2 = in.tellg();
in.close();
cout << "len1:" << length1 << endl;
cout << "len2:" << length2 << endl;
cout << "len:" << length2 - length1 << " bytes" << endl;
/***************************二进制文件读写*******************************/
fstream binInOut(filename,ios::in|ios::ate|ios::binary);
char * buffer1;
long size = binInOut.tellg();
binInOut.clear();
binInOut.seekg(0,ios::beg);
buffer1 = new char[size];
binInOut.read(buffer1, size);
cout <<"size:"<<size <<" buffer1:" << buffer1 << endl;//不知道为什么末尾会多出乱码
//cout << "buffer1:" << static_cast(buffer1) << endl;
binInOut.close();
delete[] buffer1;
/***************************字符串读写*******************************/
/* 输入字符串数据
anmy 2345 56437
daga 23456 67543
hsagg 26789 8765
输入完成后 回车+ctrl + c
*/
string line, word;
vector<PersonInfo> people;
while (getline(cin,line)){
PersonInfo info;
istringstream record(line);
record >> info.name;
while (record >> word){
info.phones.push_back(word);
}
people.push_back(info);
}
ofstream out1("test.txt", ios::out | ios::app);//ofstream 写入数据
if (out1.is_open()) {
for (int i = 0; i < people.size(); i++){
for (int j = 0; j < people.at(i).phones.size(); j++){
out1 << people.at(i).name << ends << people.at(i).phones.at(j) << endl;
cout << people.at(i).name << ends << people.at(i).phones.at(j) << endl;
}
}
out1.close();
}
for (const auto &entry : people) {
ostringstream formatted, badNums;
for (const auto &nums : entry.phones){
if (strcmp(nums.c_str(), "8766") < 0)
badNums << "bad " << nums;
else {
formatted << "ok " << nums;
}
}
if (badNums.str().empty())
cout << entry.name << " " << formatted.str() << endl;
else
cerr << "input error:" << entry.name << "invalid number " << badNums.str() << endl;
}
return 0;
}