11_IO流与流类库
IO流与流类库
IO流概念
流是信息流动的一种抽象, 在程序中的对象、文件对象 之间相互流动
流对象与文件操作
- 程序建立一个流对象
- 指定这个流对象与某个文件对象建立连接
- 程序操作流对象
- 流对象通过文件系统对所连接的文件对象产生作用。
提取与插入
- 读操作在流数据抽象中被称为(从流中)提取
- 写操作被称为(向流中)插入。
输出流
三个输出流
- ostream
- ofstream
- ostringstream
三个输出流对象
- cout 标准输出
- cerr 标准错误输出,没有缓冲,发送给它的内容立即被输出。
- clog 类似于cerr,但是有缓冲,缓冲区满时被输出。
标准输出换向:默认是输出到屏幕的
ofstream fout("b.out");
streambuf* pOld =cout.rdbuf(fout.rdbuf());
//…
cout.rdbuf(pOld);
构造输出流对象
ofstream myFile("filename");
//等价于
ofstream myFile; //声明一个静态文件输出流对象
myFile.open("filename"); //打开文件,使流对象与文件建立联系
//指定打开模式
ofstream myFile("filename", ios_base::out | ios_base::binary);
文件输出流成员函数
-
open函数, 把流与一个特定的磁盘文件关联起来。
需要指定打开模式。 -
put函数, 把一个字符写到输出流中。
-
write函数, 把内存中的一块内容写到一个文件输出流中
-
seekp和tellp函数, 操作文件流的内部指针
-
close函数, 关闭与一个文件输出流关联的磁盘文件
-
错误处理函数, 在写到一个流时进行错误处理
向文本文件输出
#include <iostream>
#include <fstream>
using namespace std;
int main() {
ofstream myFile("readme.txt");
myFile << "hello" << "world" << endl;
myFile << "huanxi" << endl;
return 0;
}
向二进制文件输出
二进制
- 存储效率高
文本文件
- 存在一个文本到二进制的转换,效率较低
#include <fstream>
using namespace std;
struct Date {
int mon, day, year;
};
int main() {
Date dt = { 6, 10, 92 };
ofstream file("date.dat", ios_base::binary);
file.write(reinterpret_cast<char *>(&dt),sizeof(dt));
file.close();
return 0;
}
向字符串输出
向内存中给的字符串输出
- 用于构造字符串
- 功能
- 支持ofstream类的除open、close外的所有操作
- str函数可以返回当前已构造的字符串
- 典型应用
- 将数值转换为字符串
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
//函数模板toString可以将各种支持“<<“插入符的类型的对象转换为字符串。
template <class T>
inline string toString(const T &v) {
ostringstream os; //创建字符串输出流
os << v; //将变量v的值写入字符串流
return os.str(); //返回输出流生成的字符串
}
int main() {
string str1 = toString(5);
cout << str1 << endl;
string str2 = toString(1.2);
cout << str2 << endl;
return 0;
}
输出结果:
5
1.2
输入流
输入流类
- istream类最适合用于顺序文本模式输入。cin是其实例。
- ifstream类支持磁盘文件输入。
- istringstream
构造输入流对象
- 如果在构造函数中指定一个文件名,在构造该对象时该文件便自动打开。 ifstream myFile("filename");
- 在调用默认构造函数之后使用open函数来打开文件。 ifstream myFile; //建立一个文件流对象 myFile.open("filename"); //打开文件"filename”
- 打开文件时可以指定模式 ifstream myFile("filename", iosbase::in | iosbase::binary);
提取运算符从文本文件输入
- 提取运算符(>>)对于所有标准C++数据类型都是预先设计好的,遇到空格结束
- 是从一个输入流对象获取字节最容易的方法。
- ios类中的很多操纵符都可以应用于输入流。但是只有少数几个对输入流对象具有实际影响,其中最重要的是进制操纵符dec、oct和hex。
相关函数
- open 把该流与一个特定磁盘文件相关联。
- get 功能与提取运算符(>>)很相像,主要的不同点是get函数在读入数据时包括空白字符。
- getline 功能是从输入流中读取多个字符,并且允许指定输入终止字符,读取完成后,从读取的内容中删除终止字符。
- read 从一个文件读字节到一个指定的内存区域,由长度参数确定要读的字节数。当遇到文件结束或者在文本模式文件中遇到文件结束标记字符时结束读取。
- seekg 用来设置文件输入流中读取数据位置的指针。
- tellg 返回当前文件读指针的位置。
- close 关闭与一个文件输入流关联的磁盘文件。
//get函数
#include <iostream>
using namespace std;
int main() {
char ch;
while ((ch = cin.get()) != EOF)
cout.put(ch);
return 0;
}
//输入流指定一个终止字符
#include <iostream>
#include <string>
using namespace std;
int main() {
string line;
cout << "Type a line terminated by 't' " << endl;
getline(cin, line, 't');
cout << line << endl;
return 0;
}
//从文件读一个二进制数据到结构体
#include <iostream>
#include <fstream>
#include <cstring>
using namespace std;
struct SalaryInfo {
unsigned id;
double salary;
};
int main() {
SalaryInfo employee1 = { 600001, 8000 };
ofstream os("payroll", ios_base::out | ios_base::binary);
os.write(reinterpret_cast<char *>(&employee1), sizeof(employee1));
os.close();
ifstream is("payroll", ios_base::in | ios_base::binary);
if (is) {
SalaryInfo employee2;
is.read(reinterpret_cast<char *>(&employee2), sizeof(employee2));
cout << employee2.id << " " << employee2.salary << endl;
} else {
cout << "ERROR: Cannot open file 'payroll'." << endl;
}
is.close();
return 0;
}
//seekg函数设置位置指针
int main() {
int values[] = { 3, 7, 0, 5, 4 };
ofstream os("integers", ios_base::out | ios_base::binary);
os.write(reinterpret_cast<char *>(values), sizeof(values));
os.close();
ifstream is("integers", ios_base::in | ios_base::binary);
if (is) {
is.seekg(3 * sizeof(int));
int v;
is.read(reinterpret_cast<char *>(&v), sizeof(int));
cout << "The 4th integer in the file 'integers' is " << v << endl;
} else {
cout << "ERROR: Cannot open file 'integers'." << endl;
}
ret
//读一个文件并显示其中0元素位置
int main() {
ifstream file("integers", ios_base::in | ios_base::binary);
if (file) {
while (file) {//读到文件尾file为0
streampos here = file.tellg();
int v;
file.read(reinterpret_cast<char *>(&v), sizeof(int));
if (file && v == 0)
cout << "Position " << here << " is 0" << endl;
}
} else {
cout << "ERROR: Cannot open file 'integers'." << endl;
}
file.close();
return 0;
}
从字符串输入流读取
- 用于从字符串读取数据
- 在构造函数中设置要读取的字符串
- 功能
- 支持ifstream类的除open、close外的所有操作
- 典型应用
- 将字符串转换为数值
template <class T>
inline T fromString(const string &str) {
istringstream is(str); //创建字符串输入流
T v;
is >> v; //从字符串输入流中读取变量v
return v; //返回变量v
}
int main() {
int v1 = fromString<int>("5");
cout << v1 << endl;
double v2 = fromString<double>("1.2");
cout << v2 << endl;
return 0;
}
输出结果:
5
1.2
istringstream istr("5 1.2");
int a;
float b;
istr >> a >> b;
a=5, b=1.2
输入输出流
- 一个iostream对象可以是数据的源或目的。
- 两个重要的I/O流类都是从iostream派生的,它们是fstream和stringstream。这些类继承了前面描述的istream和ostream类的功能。
fstream类
- fstream类支持磁盘文件输入和输出。
- 如果需要在同一个程序中从一个特定磁盘文件读并写到该磁盘文件,可以构造一个fstream对象。
- 一个fstream对象是有两个逻辑子流的单个流,两个子流一个用于输入,另一个用于输出。
stringstream类
- stringstream类支持面向字符串的输入和输出
- 可以用于对同一个字符串的内容交替读写,同样是由两个逻辑子流构成。