# 流对象与文件操作
- 程序建立一个流对象
- 当程序与
外界环节
进行信息交流时,存在着两个对象,一个是程序中的对象,另一个是文件对象 - 流是一种抽象,它负责在数据的生产者和数据的消费者之间建立联系,并管理
数据的流动
- 指定这个流对象与某个文件对象建立连接
- 程序操作流对象
- 流对象通过文件系统对所连接的文件产生作用
# 提取与插入
- 读操作在流数据抽象中被称为 (从流中) 提取
- 写操作被称为 (向流中) 插入
类名 | 说明 | 包含文件 |
---|
抽象流基类 | | |
ios | 流基类 | ios |
输入流类 | | |
istream | 通用输入流类和其它输入流的基类 | istream |
ifstream | 文件输入流类 | fstream |
istringstream | 字符串输入流类 | sstream |
输出流类 | | |
ostream | 通用输出流类和其它输出流的基类 | ostream |
ofstream | 文件输出流类 | fstream |
ostringstream | 字符串输出流类 | sstream |
输入 / 输出流类 | | |
iostream | 通用输入 / 输出流类和其它输入 / 输出流的基类 | istream |
fstream | 文件输入 / 输出流类 | fstream |
stringstream | 字符串输入 / 输出流类 | sstream |
流缓冲区类 | | |
streambuf | 抽象流缓冲区基类 | streambuf |
filebuf | 磁盘文件的流缓冲区类 | fstream |
stringbuf | 字符串的流缓冲区类 | sstream |
# 预先定义的输出流对象
cout
标准输出cerr
标准错误输出, 没有缓冲
,发送给他的内容立即被输出clog
类似 cerr
, 但 有缓冲
,缓冲区满时被输出
# 构造输出流对象
| ofstream myFile("filename"); |
- 可以在调用默认构造函数之后使用
open
成员函数打开文件
| ofstream myFile; |
| myFile.open("filename"); |
- 在构造对象或用 open 打开文件时可以指定模式,默认存文本文件
| ofstream myFile("filename",iso_base::out | ios_base::binary); |
# 文件输出流成员函数
- 与操作符等价的成员函数
- 执行
非格式化
写操作的成员函数 - 其它修改流状态且不同于操作符或插入运算符的成员函数
# 文件输出流成员函数
open
函数put
函数write
函数- 把内存中的一块内容写到一个文件输出流中 (写
二进制
文件用)
seekp
和 tellp
函数- 操作文件流的
内部指针
, seekp
写到什么位置标志tellp
告诉文件位置,开始的字节数
close
函数- 错误处理函数
# 向文本文件输出
# 插入运算符
- 插入 (
<<
) 运算符- 传送字节到输出流对象,为所有标准 C++ 数据类型预先设计
# 操作符 ( manipulator
)
ios_base
类中 (如 hex(),<iomanio>头文件(如setprecision())
)
- 控制输出宽度
- 在流中放入
setw
操作符或调用 width
成员函数为每个项指定输出宽度
setw
和 width
仅影响紧随其后的输出项,但其它流格式操纵符保存有效指导发生改变dec
, oct
和 hex
操作符设置输入和输出的默认进制
| #include <iostream> |
| using namespace std; |
| int main(void) |
| { |
| double values[] = { 1.23,35.36,653.7,4358.24 ,124567899}; |
| for (int i = 0; i < 5; i++) |
| { |
| |
| |
| cout.width(10); |
| cout << values[i] << endl; |
| } |
| return 0; |
| } |
| |
| 1.23 |
| 35.36 |
| 653.7 |
| 4358.24 |
| 1.24568e+08 |
| */ |
# 输出到文本
| #include <fstream> |
| using namespace std; |
| int main(void) |
| { |
| ofstream txtout("file1.txt"); |
| double values[] = { 1.23,35.36,653.7,4358.24 ,124567899 }; |
| for (int i = 0; i < 5; i++) |
| { |
| txtout.width(10); |
| txtout << values[i] << endl; |
| } |
| txtout.close(); |
| return 0; |
| } |
# 一行多输出,宽度,对齐,精度
| #include <iostream> |
| #include <iomanip> |
| #include <string> |
| using namespace std; |
| int main(void) |
| { |
| double values[] = { 1.23,35.36,653.7,4358.24 }; |
| string names[] = { "Zoot","Jimmy","AI","Stan" }; |
| for (int i = 0; i < 4; i++) |
| { |
| cout << setw(6) << names[i] |
| << setw(10) << values[i] << endl; |
| } |
| |
| cout << "设置对齐方式" << endl; |
| for (int i = 0; i < 4; i++) |
| { |
| cout << setiosflags(ios_base::left) |
| << setw(6) << names[i] |
| << setw(10) << values[i] << endl; |
| } |
| |
| cout << "控制输出精度" << endl; |
| cout << setiosflags(ios_base::fixed); |
| for (int i = 0; i < 4; i++) |
| { |
| cout << setiosflags(ios_base::left) |
| << setw(6) << names[i] |
| << setw(10) << values[i] |
| << resetiosflags(ios_base::left) |
| << setw(10) << setprecision(1) <<values[i] |
| <<endl; |
| } |
| |
| |
| cout << "控制输出精度scientific" << endl; |
| cout << setiosflags(ios_base::scientific); |
| for (int i = 0; i < 4; i++) |
| { |
| cout << setiosflags(ios_base::left) |
| << setw(6) << names[i] |
| << resetiosflags(ios_base::left) |
| << setw(10) << setprecision(1) << values[i] |
| << endl; |
| } |
| |
| return 0; |
| } |
| |
| Zoot 1.23 |
| Jimmy 35.36 |
| AI 653.7 |
| Stan 4358.24 |
| 设置对齐方式 |
| Zoot 1.23 |
| Jimmy 35.36 |
| AI 653.7 |
| Stan 4358.24 |
| 控制输出精度 |
| Zoot 1.230000 1.2 |
| Jimmy 35.4 35.4 |
| AI 653.7 653.7 |
| Stan 4358.2 4358.2 |
| 控制输出精度 scientific |
| Zoot 0x1.3ae147ae147aep+0 |
| Jimmy 0x1.1ae147ae147aep+5 |
| AI 0x1.46d999999999ap+9 |
| Stan 0x1.1063d70a3d70ap+12 |
| */ |
# setiosflags
操作符
- 头文件
iomanip
ios_base::前缀
setiosflags
不同于 width
和 setw
,它的影响是持久的,直到 resetiosflags
重新恢复默认值时为止setiosflags
的参数是该流的格式标志值,可用按位或 (|) 运算符就行组合
# setiosflags
参数
流的格式标识
ios_base::skipws
在输入中跳过空白 。ios_base::left
左对齐值,用填充字符填充右边。ios_base::right
右对齐值,用填充字符填充左边(默认对齐方式)。ios_base::internal
在规定的宽度内,指定前缀符号之后,数值之前,插入指定的填充字符。ios_base::dec
以十进制形式格式化数值(默认进制)。ios_base::oct
以八进制形式格式化数值 。ios_base::hex
以十六进制形式格式化数值。ios_base::showbase
插入前缀符号以表明整数的数制。ios_base::showpoint
对浮点数值显示小数点和尾部的 0 。ios_base::uppercase
对于十六进制数值显示大写字母 A 到 F,对于科学格式显示大写字母 E 。ios_base::showpos
对于非负数显示正号(“+”)。ios_base::scientific
以科学格式显示浮点数值。ios_base::fixed
以定点格式显示浮点数值(没有指数部分) 。ios_base::unitbuf
在每次插入之后转储并清除缓冲区内容。
# 精度
- 浮点数输出精度的默认值是
6
, 例如:3466.98 - 改变精度:
setprecision
操作符 (头文件 iomanip
中) - 如果不指定 fixed 或 scientific, 精度值表示有效数字位数
- 如果设置了
ios_base::fixed
或 ios_base::scientific
精度值表示 小数点之后的位数
# 二进制文件流
- 使用
ofstream
构造函数中的模式参数指定 二进制输出模式
- 以通常方式构造一个流,然后使用
setmode
成员函数,在文件打开后改变模式; - 通过二进制文件输出流对象完成输出
| #include <fstream> |
| using namespace std; |
| struct Date |
| { |
| int mon, day, year; |
| }; |
| int main(void) |
| { |
| Date dt = { 6,10,92 }; |
| ofstream file("date.dat", ios_base::binary); |
| file.write(reinterpret_cast<char*>(&dt), sizeof(dt)); |
| file.close(); |
| } |
# 向字符串输出
将字符串作为输出流的目标,可以实现将其他数据类型转换为字符换的功能
# 字符串输出流
- 用于构造字符串
- 功能
- 支持
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; |
| return os.str(); |
| } |
| int main(void) |
| { |
| string str1 = toString(5); |
| cout << str1 << endl; |
| string str2 = toString(1.2); |
| cout << str2 << endl; |
| return 0; |
| } |
| |
| 5 |
| 1.2 |
| */ |
# 输入流
tream
类最适合用于顺序文本模式输入, cin
是实例ifstream
类支持磁盘文件输入istringstram
# 构造输入流对象
- 如果在构造函数中指定一个文件名,在构造该对象时该文件便自动打开。
| ifstream myFile("filename"); |
- 在调用默认构造函数之后使用 open 函数来打开文件。
| ifstream myFile; |
| myFile.open("filename"); |
| |
| ifstream myFile("filename", ios_base::in | ios_base::binary); |
# 使用 提取运算符
从文本文件输入
- 提取运算符 (>>) 对于所有标准 c++ 数据类型预先设计
- 是从一个输入流对象获取直接最容易的方法
ios
类中很多操纵符都可以应用于输入流,但是只有少数几个对输入流对象具有实际影响,最重要 的是进制操作符 dec十进制
, oct八进制
和 hex十六进制
# 输入流相关函数
open函数
把该流与一个特定磁盘文件相关联。get函数
的功能与提取运算符 (>>) 很相像,主要的不同点是 get 函数在读入数据时包括 空白字符
。getline
的功能是从输入流中读取多个字符,并且允许指定输入终止字符,读取完成后,从读取的内容中删除终止字符。read成员函数
从一个文件读字节到一个指定的内存区域,由长度参数确定要读的字节数。当遇到文件结束或者在文本模式文件中遇到文件结束标记字符时结束读取。seekg函数
用来设置文件输入流中读取数据位置的指针。tellg函数
返回当前文件读指针的位置。close函数
关闭与一个文件输入流关联的磁盘文件。
| |
| get 函数应用 |
| */ |
| #include <iostream> |
| using namespace std; |
| int main(void) |
| { |
| char ch; |
| |
| while ((ch = cin.get()) != EOF) |
| { |
| cout.put(ch); |
| } |
| |
| return 0; |
| } |
| |
| 为输入流指定一个终止字符 |
| */ |
| |
| #include <iostream> |
| #include <string> |
| using namespace std; |
| int main(void) |
| { |
| string line; |
| cout << "Type a line terminated by '\t'" << endl; |
| getline(cin, line, '\t'); |
| cout << line << endl; |
| } |
| |
| 从文件中读一个二进制记录到一个结构体 |
| */ |
| #include <iostream> |
| #include <fstream> |
| #include <cstring> |
| using namespace std; |
| struct SalaryInfo |
| { |
| unsigned id; |
| double salary; |
| }; |
| int main(void) |
| { |
| 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 函数设置位置指针 |
| */ |
| #include <iostream> |
| #include <fstream> |
| #include <cstring> |
| using namespace std; |
| int main(void) |
| { |
| 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; |
| } |
| return 0; |
| } |
| |
| 读入一个文件并显示出其中 0 元素的位置 |
| */ |
| #include <iostream> |
| #include <fstream> |
| #include <cstring> |
| using namespace std; |
| int main(void) |
| { |
| ifstream file("integers", ios_base::in | ios_base::binary); |
| if (file) |
| { |
| while (file) |
| { |
| |
| streampos here = file.tellg(); |
| int v; |
| file.read(reinterpret_cast<char*>(&v), sizeof(int)); |
| if (file && v == 0) |
| cout << "Position:\t" << here << "\tis 0" << endl; |
| } |
| } |
| else |
| { |
| cout << "ERROR:Cannot open file \"integers\"." << endl; |
| } |
| file.close(); |
| } |
# 从字符串输入
将字符串作为文本输入流的源,可以经字符串转换为其他数据类型
# 字符串输入流 ( istringstream
)
- 用于从
字符串读取数据
- 在构造函数中设置要读取的字符串
- 功能
- 支持
ifstream
类的除 open,close
外的所有操作
- 典型应用
| |
| #include <iostream> |
| #include <sstream> |
| #include <string> |
| using namespace std; |
| |
| template <class T> |
| inline T fromString(const string& str) |
| { |
| istringstream is(str); |
| T v; |
| is >> v; |
| return v; |
| } |
| |
| int main() |
| { |
| int v1 = fromString<int>("5"); |
| cout << v1 << endl; |
| double v2 = fromString<double>("1.2"); |
| cout << v2 << endl; |
| return 0; |
| } |
# 重要输入 / 输出流
- iostream 对象可以是数据的源或目的
- 两个重要的 I/O 流类都是从 iostream 派生,他们是 fstream 和 stringstream
- 这些类继承了前面描述的 istream 和 ostream 类功能
# fstream 类
- fstream 类支持磁盘文件输入和输出
- 可构造 fstream 实现从一个特定磁盘文件读并谢大鹏磁盘 文件
- 一个 fstream 对象是 有两个逻辑 子流的单个流,两个子流一个用于输入,另一个用于输出
# stringstream 类
- stringstream 类支持面向字符串的输入和输出
- 可以用于对同一个字符串的内容交换读写 ,同样是由两个逻辑子流构成
# getline
读取文本练习
| #include <iostream> |
| #include <fstream> |
| #include <string> |
| #include <iomanip> |
| #include <istream> |
| using namespace std; |
| |
| int main(void) |
| { |
| |
| ofstream textout("test.txt",ios_base::out | ios_base::binary); |
| string hello = "hello test\nhello second!"; |
| |
| textout |
| |
| <<hello<<endl; |
| textout.close(); |
| |
| |
| ifstream myFile("test.txt", ios_base::in | ios_base::binary); |
| string out; |
| while (myFile) |
| { |
| |
| |
| |
| getline(myFile, out); |
| cout << out << endl; |
| } |
| |
| { |
| cout << "ERROR:Cannot open file 'text.txt'" << endl; |
| }*/ |
| myFile.close(); |
| return 0; |
| } |
C++ 参考文档