C++ IO流小结

撒花庆祝下,终于看完了(C++Primer)第一部分,即将进入第二部分!

IO部分,最基本的是iostream(istream、ostream),子类有fstream(ifstream、ofstream)和sstream(istringstream、ostringstream)。

iostream是控制窗口输入输出。

fstream是文件输入输出。

sstream是字符串输入输出(内存中)。

如果两种类型存在继承关系,则可以说一个类“继承”了其父类的行为——接口。

C++ 中所提及的父类称为基类(base class) ,而继承而来的类 则称为派生类(derived class)

IO 类型在三个独立的头文件中定义:

iostream 定义读写控制窗口的类型, fstream 定义读写已命名文件的类型,而 sstream 所定义的类型则用于读写存储在内存中的 string 对象。

在 fstream 和 sstream 里定义的每种类型都是从 iostream 头文件中定义的相关类型派生而来。

wchar_t、wiostream。。。

IO流不允许赋值或者复制

所以,

①函数形参和返回值不能是IO流对象,必须是引用,而且形参不能是const--因为读写都会改变状态。

②只有支持复制的元素类型可以存储在 vector 或其他容器类型里。由于流对象不能复制,因此不能存储在 vector (或其他)容器中 (即不存在存储流对象的 vector 或其他容器)。

所有的流对象,都包含一个条件状态成员,该成员由setstate clear 操作管理。该成员类型为iostate 。另外有三个常量,代表三种状态,可进行位操作。badbitfailbiteofbit

流的状态检查操作则有:bad、fail、eof、good。如果bad、fail、eof中任一个返回true,则流处于错误状态。否则good操作返回true。

clear和setstate操作用于改变条件成员的状态。clear会重设为有效状态。setstate用于打开某个条件,用于表示某个问题的发生。setstate会保留其他状态。

IO缓冲区每个io流对象都管理一个缓冲区!用于存储程序读写的数据。

除了自动刷新缓冲区之外,还可以手动刷新缓冲区:endl、flush、ends。

另外,如果想让io流刷新输出每次读写的数据,可以使用unitbuf

cout<<unitbuf<<"first"<<" second"<<nounitbuf ; //相当于cout<<"first"<<flush<<"second"<<flush ;

警告:如果程序崩溃了,则不会刷新缓冲区!!    这个特性可以用来查找错误,只能是在最后输出语句的后面。

----------------------------------

当输入流和输出流绑到一起时,任何读输入流的尝试,都将刷新其输出流关联的缓冲区。

标准库将cout和cin绑定到一起,所以,任何cin语句,都会导致cout缓冲区的刷新。

注意:只是刷新!没有传递数据!!!且一个对象只能绑定一个对象。

交互式系统通常应确保它们的输入和输出流是绑在一起的。这样可以保证任何输出都是在试图读之前进行。

cin.tie(0); //断开默认的tie(默认cin.tie(&cout))
cin.tie(&cerr); //重新绑定

----------------------------------

文件操作:

fstream 类型除了继承下来的行为外,还定义了两个自己的新操作—— open close,以及形参为要打开的文件名的构造函数。

需要读写文件时,则必须定义自己的对象,并将它们绑定在需要的文件上。

假设 ifile 和 ofile 是存储希望读写的文件名的 strings 对象,可如下编写代码:

// construct an ifstream and bind it to the file named ifile
ifstream infile(ifile.c_str());
// ofstream output file object to write file named ofile
ofstream outfile(ofile.c_str());

也可以如下编写代码:

ifstream infile;
ofstream outfile;

infile.open(ifile.c_str());
outfile.open(ofile.c_str());

为了实现读写,需要将指定的文件打开并定位,open 函数完成系统指定的所有需要的操作。

打开文件后,检查是否正确打开是个好习惯:if(!infile)...//如果没打开。

注意:历史原因,只能使用C风格字符串作为文件名。

#include <iostream>
#include <string>

using namespace std;

int main(){

    cout<<"endl!"<<endl;
    cout<<"flush!"<<flush;//
    cout<<"null-terminated ends!"<<ends;

    cout<<"\r\n";
    //一次性刷新所有输出
    cout<<unitbuf<<"first"<<" second"<<nounitbuf; //cout<<"first"<<flush<<"second"<<flush;

    cout<<"\r\n";
    ///=----------------------
    ostream *old_tie = cin.tie();
    cout<<"old_tie:"<<old_tie<<endl;
    cin.tie(0);
    cin.tie(&cerr); //why &?

    cerr.tie(0);
    cerr.tie(&cout);

    string str;
    cin>>str;
    cerr<<"hehe";//如何不刷新?
    cerr<<"hehe";//如何不刷新? 

    cin>>str;//再来一次
    cerr<<str;
    cout<<str;

    return 0;
}
#include <iostream>
#include <fstream>
#include <string>

using namespace std;

int main(){
    string infile="abc";
    string outfile="abc";
    ifstream in(infile.c_str());
    ofstream out(outfile.c_str());

    if(!in){
        cerr<<"Error: unable to open file:"<<infile<<endl;
        return -1;
    }
    if(!out){
        cerr<<"Error: unable to open file:"<<outfile<<endl;
        return -1;
    }

    return 0;
}
//这个代码有问题,忽略吧
#include <iostream>
#include <string>
#include <stdexcept>

using namespace std;

void run1();
void run2();
istream &getistream(istream &in);

int main(){
    run1();
//    run2();
//
//    getistream(cin);//注意,io流不可复制或赋值。
//    if(cin){
//        cout<<"OK!"<<endl;
//    }else{
//        cout<<"sth is wrong"<<endl;
//        if(cin.eof()){
//            cout<<"eof was not cleared!"<<endl;
//        }
//        if(cin.bad()){
//            cout<<"bad was not cleared!"<<endl;
//        }
//        if(cin.fail()){
//            cout<<"fail was not cleared!"<<endl;
//        }
//        return -1;
//    }

    return 0;
}

void run1(){
    int val;
    while(cin>>val, !cin.eof()){//有输入,不是结尾,就继续 。逗号运算符,返回右边的结果
        if(cin.bad()){
            cout<<"input stream damaged!"<<endl;
            throw runtime_error("IO stream corrupted");
        }
        if(cin.fail()){
            cerr<<"bad input!"<<endl;
//            cin.clear(istream::failbit);//
//            cin.clear();
//            cin.clear(istream::goodbit);
            cin.clear(istream::failbit);
            cin.clear(istream::badbit);
            cin.clear(istream::eofbit);
//            cin.clear();//why this does not work? 

//            cin.ignore(std::numeric_limits<std::streamsize>::max(), ‘\n‘);
            cout<<"try again.."<<endl;
            continue;
        }
        cout<<val<<endl;
    }
}

void run2(){
    string str;
    cout<<"type sth .."<<endl;
    cin>>str;
    iostream::iostate old_state= cin.rdstate();//
    cout<<old_state<<endl;
    cin.clear();//what?
    //...
    cin.clear(old_state);//清除旧状态,而非设置旧状态!设置应该是setstate。这里书上弄错了吧。 

}

istream &getistream(istream &in){
//    iostream::iostate old_state = in.rdstate();
    cout<<"type sth.."<<endl;

    string str;
    while(in>>str, !in.eof()){
        //
        if( in.fail() || in.bad()){
            cerr<<"fail or bad";
            in.clear();
            continue;
        }
        cout<<"you typed: "<<str<<endl;
    }
//    in.setstate(old_state);
//    in.clear(old_state);//for what?
    in.clear();//恢复正常
    return in;
}
#include <iostream>
#include <fstream>
#include <string>
#include <vector>

using namespace std;
ifstream &openfile(ifstream &in, string &filename);
ofstream &savefile(ofstream &out, string filename);

//复制文件练习
int main(){
    string filename="e:/DbUtil.java";
    string filename2="e:/DbUtil1.java";
    ifstream in;
    ofstream out;
    openfile(in, filename);
    savefile(out,filename2);

    string line;
    while(getline(in, line)){
        out<<line<<endl;
    }
    in.close();
    out.close();

    return 0;
}

ifstream &openfile(ifstream &in, string &filename){
    in.close();
    in.clear();

    in.open(filename.c_str());

    return in;
}

ofstream &savefile(ofstream &out, string filename){
    out.close();
    out.clear();

    out.open(filename.c_str(),ofstream::app);
    return out;
}

----------------------------------

打开文件需要指定打开的mode,这是文件自身的属性!

mode:in、out、app、ate、trunc、binary。

单纯以out打开,会丢失所有内容。类似out|trunc。

fstream对象默认以in|out模式打开,不清空!!!

fstream inOut("xxx", fstream::in | fstream::out);

ate是个什么鬼?app会在每次写操作之前都把写指针置于文件末尾,而ate模式则只在打开时才将写指针置于文件末尾。ate模式在文件操作过程中,可以通过seekp等操作移动指针位置。

------------------------------------------------

sstream,用于从内存中的字符串读取数据,或,向内存中的字符串写入数据!

也可以用于格式转换!!!其实就是通过特定类型的变量来接收!

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>

using namespace std;
ifstream &openfile(ifstream &in, string &filename);

int main(){
    string filename="e:/DbUtil.java";
    ifstream in;
    openfile(in, filename);

    string line, word;

    while(getline(in, line)){
        istringstream strin(line);
        ostringstream strout(line);
        while(strin>>word){
            strout<<word<<endl;//输出到string了,看不到
            cout<<word<<endl;//输出string到控制台
        }
    }
    in.close();
    in.clear();

    return 0;
} 

ifstream &openfile(ifstream &in, string &filename){
    in.close();
    in.clear();

    in.open(filename.c_str());

    return in;
}
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>

using namespace std;

//字符串格式转换
int main(){

    int val1=100,val2=500;
    string line, word;
    ostringstream out;
    out<<"val1: "<<val1<<"\n"
        <<"val2: "<<val2<<"\n";

    cout<<out.str()<<endl;

    string dump;

    istringstream in(out.str());
    in>>dump>>val1>>dump
        >>dump>>val2>>dump;

    cout<<val1<<"--"<<val2<<endl;    

    return 0;
} 

参考:

  ios::app与ios::ate的区别

时间: 2024-11-05 21:43:26

C++ IO流小结的相关文章

Java API —— IO流小结

练习题: 1.复制文本文件 package cn.itcast_01; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; /* * 复制文本文件 * * 分析: * 复制数据,如果我们知道用记事本打开并能够读懂,就用字符流,否则用字节流. * 通过该原理,我们知

JavaSE_ IO流 总目录(19~22)

黑马程序员_JavaSE学习总结第19天_IO流119.01 集合的特点和数据结构总结19.02 如何选择使用哪种集合19.03 集合常见功能和遍历方式总结19.04 异常的概述和分类19.05 JVM默认处理异常19.06 try...catch的方式处理异常1(一个异常)19.07 try...catch的方式处理异常2(两个异常)19.08 JDK7针对多个异常的处理方案19.09 编译期异常和运行期异常的区别19.10 Throwable的几个常见方法19.11 throws的方式处理异

java基础(二十)IO流(三)

这里有我之前上课总结的一些知识点以及代码大部分是老师讲的笔记 个人认为是非常好的,,也是比较经典的内容,真诚的希望这些对于那些想学习的人有所帮助! 由于代码是分模块的上传非常的不便.也比较多,讲的也是比较清晰的!如果你有需要可以在评论中留下您的邮箱我看到一定会免费发给你的!感谢这个平台让我们大家共同进步吧!! 记住 程序员是无私的!!! 也非常欢迎到我的博客内观看 博客地址:http://www.cnblogs.com/duscl/ /* 1:字符流(掌握) (1)字节流操作中文数据不是特别的方

第10章:IO流

IO流 IO流 |--字节流 |--字节输入流 InputStream int read():一次读取一个字节 int read(byte[] bys):一次读取一个字节数组 |--FileInputStream |--BufferedInputStream |--字节输出流 OutputStream void write(int by):一次写一个字节 void write(byte[] bys,int index,int len):一次写一个字节数组的一部分 |--FileOutputStr

java常用IO流数据流小结

  类名 常用方法 说明 输入流 InputStream int read(); 只能读字节流,虽然返回值是int,但只有低8位起作用. DataInputStream Type readType(); 可以读二进制流,可以读byte,short,int,long,double等二进制流. BufferedReader String readLine(); 可以读文本行. 输出流 OutputStream void write(int); 只能写字节流,虽然形参是int,但只有低8为起作用. D

流 JAVA /IO 基本小结

流 JAVA /IO 基本小结 通过一行常见的代码讨论:new BufferedReader(new InputStreamReader(System.in)) java的IO是基于流(stream)概念的,什么是流呢,作为初学者,我是这样理解的,在各个应用之间传送的是BITS,这些BIT可已被认为是流体,可以就认为是水流,那么用来在各个水源之间转移水的工具应该选择什么呢?一般情况下,水管是可以的,所以数据我将数据源比作水源,将流对象比作水管这样就有了对流的第一步认识,它再也不神秘了.对于流,我

(转载) java:IO流学习小结

今天刚刚看完Java的io流操作,把主要的脉络看了一遍,不能保证以后使用时都能得心应手,但是最起码用到时知道有这么一个功能可以实现,下面对学习进行一下简单的总结: IO流主要用于硬板.内存.键盘等处理设备上得数据操作,根据处理数据的数据类型的不同可以分为:字节流(抽象基类为InPutStream和OutPutStream)和字符流(抽象基类为Reader和Writer).根据流向不同,可以分为:输入流和输出流.  其中主要结构可以用下图来表示:  字符流和字节流的主要区别: 1.字节流读取的时候

IO流理解方式小结

从业以来一直对IO不甚了解,每次看到都头疼不已,最近有时间小小的总结一下,下面以FileIO流为try            byte[] byt = new byte[3]; //文件输入流 FileInputStream in = new FileInputStream(new File("C:\\Users\\Administrator\\Desktop\\1.txt")); //文件输出流,输出文件与输入文件为同一件文件 FileOutputStream out = new F

Java笔记(19):IO流(01)

1.try...catch的方式处理异常1 1 package cn.itcast_02; 2 3 /* 4 * 异常:程序出现了不正常的情况. 5 * 6 * 程序的异常:Throwable 7 * 严重问题:Error 我们不处理.这种问题一般都是很严重的,比如说内存溢出. 8 * 问题:Exception 9 * 编译期问题:不是RuntimeException的异常 必须进行处理的,因为你不处理,编译就不能通过. 10 * 运行期问题:RuntimeException 这种问题我们也不处