1.流有着状态,IO库定义了一个与机器无关的iostate类型,它提供了表达流状态的完整功能,流有四种状态,badbit代表系统级错误,failbit表示一个IO操作失败,eofbit代表已经到了文件的结束,goodbit代表流是否发生错误,如果goodbit的值为0,那么就代表流未发生错误。
当我们使用如下的代码时:
while(cin >> word){}
实际上,我们这行代码就等价于!fail().我们应该使用good 或者是 fail 来确定流的总体状态。
2.我们可以自己管理流的状态:我们可以调用流的成员函数 rdstate(),这个函数可以得到一个类型为iostate的值,对应流的当前状态。我们还可以调用clear()函数,把流的状态置为有效(无论之前的状态是什么样),在调用clear()函数之后,我们再调用good()函数,一定可以得到一个true的值,代表我们的流的状态是有效的,我们也可以调用setstate()这个函数,来手动地改变流的状态。
3.管理输出缓冲:每一个输出流都管理着一个缓冲区,用来保存程序读写的数据.缓冲机制的作用:操作系统可以将程序的多个输出操作组合成单一的系统级写操作,会带来很大的性能提升。 缓冲刷新(概念):数据真正写到输出设备或者文件。
导致缓冲刷新的原因一般有:
1.程序正常结束,作为main函数的return操作的一部分。
2.缓冲区满时,需要刷新缓冲,之后新的数据才能继续写入缓冲区。
3.我们可以使用操纵符像endl,来显式刷新缓冲区。
4.使用unitbuf来设置流的内部状态,清空缓冲区。 cout << unitbuf;这一句就相当于所有输出操作后都会立即刷新缓冲区,cout << nounitbuf;这一句就相当于回到正常的缓冲方式。
5.一个输出流可能会被关联到一个流上面,在这种情况下,当读写被关联的流时,关联到的流的缓冲区会被刷新。
绑定两个流:X.tie(&o) 代表的是X流已经绑定到了输出流o上面,传入的参数是流的指针,而不是流的引用,我们假如要彻底解开流的关联,我们应该传递一个空指针(nullptr)。
4.文件的输入和输出:
两个关键点:1.文件流对象,2.文件名。可以在构造一个文件流对象的时候把文件名(可以是string类型的对象,也可以是C风格的指针)传入构造函数,直接打开文件,也可以手动调用文件流对象的open函数,open也是接受一个文件名参数。
一些代码:
file.h
#ifndef FILE_H
#define FILE_H
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
std::vector<std::string> getFileContent(std::ifstream& in);
void outPutToFile(std::ofstream& out, const std::vector<std::string>& target);
#endif
file.cpp
#include "file.h"
std::vector<std::string> getFileContent(std::ifstream& in)
{
std::vector<std::string> currentVector;
std::string currentWord;
while (in)
{
in >> currentWord;
currentVector.push_back(currentWord);
}
return currentVector;
}
void outPutToFile(std::ofstream& out, const std::vector<std::string>& target)
{
for (std::vector<std::string>::size_type i = 0; i != target.size(); ++i)
{
out << i << target[i] << std::endl;
}
}
main.cpp
#include "file.h"
int main(int argc, char* argv[])
{
std::string inputFile("./input.txt");
std::string outputFile("./output.txt");
std::ifstream in(inputFile);
std::ofstream out(outputFile);
if (in && out)
{
std::vector<std::string> current = getFileContent(in);
oututPutToFile(out,current);
}
in.close();
out.close();
return 0;
}
编译: g++ --std=c++11 file.h file.cpp main.cpp 执行 ./a.out
我用来测试的文件里面的单词之间有1到多个空格,而且每一行的单词数量不一样,但是ifstream这个对象还是能正确地把每一个单词读入vector里面,因为直接使用ifstream对象的>>操作符,会默认把空格符,换行符自动当做分界符来处理,所以能正常运行。
5.在使用ifstream 和 ofstream 的时候 千万要检查流的状态,因为如果open失败,那么这个流的failbit 会被置位,good()会返回false,文件流对象也遵循作用域的规则:当一个fstream 对象被销毁时,close()会被自动调用。
6.文件模式:
1.in 读方式
2.out 写方式
3.app(append) 在每一次写文件之前定位到文件末尾
4.ate(at end) 在打开文件的时候就定位到文件末尾
5.trunc 截断文件
6.binary 以二进制方式进行IO
流的模式在这些中,但是要遵循一些条件:对应条件(输入就是in,不能是out...),默认条件(如果是out模式,那么文件默认被截断)特定条件(只有trunc没有被设定的时候,我们才能指定使用app模式,在app模式下,即使没有显式指定out,文件也总是以输出方式被打开)
如果没有指定app模式,那么输出文件的之前的数据都会被覆盖掉。