• IO相关2(文件输入输出)


    除了继承自 iostream 类型的行为之外,fstream 中定义的类型还增加了一些新的成员来管理与流相关的文件。我们可以对 fstream,ifstream 和 ofstream 对象调用这些操作,但不能对其他 IO 类型调用这些操作:

    1     fstream fstrm;//创建一个未绑定的文件流.fstream是头文件fstream中定义的一个类型
    2     fstream fstrm1(s);//创建一个fstream,并打开名未s的文件.s可以是string类型或者是一个指向c风格字符串的指针.这些构造函数都是explicit的。默认的文件模式mode依赖于fstream的类型
    3     fstream fstrm2(s, mode);//与前一个构造函数类似,但指定mode打开文件
    4     fstrm.open(s);//打开名为s的文件,并将文件与fstrm绑定.s可以是一个string或一个指向c风格字符串的指针.默认的文件mode依赖于fstream的类型.返回void
    5     fstrm.close();//关闭fstrm绑定的文件.返回void
    6     fstrm.is_open();//返回一个bool值,指出与fstrm关联的文件是否成功打开且尚未关闭

    使用文件流对象:

    ifstream in(ifile);//构造一个ifstram并打开给定文件
    ofstream out;//输出文件流未关联到任何文件

     1 #include <iostream>
     2 #include <fstream>
     3 using namespace std;
     4 
     5 char const *filename = "D:\code\c++\ac27.text";
     6 
     7 string str;
     8 
     9 int main(void){
    10     ofstream file(filename);
    11     if(!file) return 0;
    12     file << "hello world!" << endl;
    13     file.close();
    14 
    15     ifstream out;
    16     out.open(filename);
    17     while(out >> str){
    18         cout << str << endl;
    19     }
    20     out.close();
    21     return 0;
    22 }

    用 fstream 代替 iostream&

    在要求使用基类对象的地方,我们可以用继承类型的对象来替代。因此,如果一个函数接受一个 ostream& 参数,我们在调用这个函数时,可以传递给他一个 ofstream 对象,对 istream& 和 ifstream 也是类似的:

     1 #include "Sales_data.h"
     2 #include <iostream>
     3 #include <fstream>
     4 using namespace std;
     5 
     6 int main(int argc, char const *argv[]){
     7     ifstream input(argv[1]);
     8     ofstream output(argv[2]);
     9     Sales_data total;
    10     if(read(input, total)){
    11         Sales_data trans;
    12         while(read(input, trans)){
    13             if(total.isbn() == trans.isbn()) total += trans;
    14             else{
    15                 print(output, total) << endl;
    16                 total = trans;
    17             }
    18         }
    19         print(output, total) << endl;
    20     }else cerr << "NO data?" << endl;
    21     return 0;
    22 }

    read 和 print 两个函数定义时指定的形参分别时 istream& 和 ostream&,但我们可以传递 fstream 对象。

    自动构造和析构:

    考虑这样一个程序,它的 main 函数接受一个要处理的文件列表:

     1 #include <iostream>
     2 #include <fstream>
     3 using namespace std;
     4 
     5 const string gel("D:\code\c++\");
     6 
     7 void process(ifstream &input){
     8     string str;
     9     input >> str;
    10     cout << str << endl;
    11 }
    12 
    13 int main(int argc, char const *argv[]){
    14     for(int i = 1; i < argc; i++){
    15         const string filename = (char)(i - 1 + 'a') + (string)".txt";
    16         // cout << filename << endl;
    17         ofstream output(gel + filename);
    18         output << filename << endl;
    19         // output.close();//fstream对象离开其作用域时,与之联系的文件自动关闭(close会自动调用)
    20     }
    21 
    22     //对每个传递给程序的文件执行循环操作
    23     for(auto p = argv + 1; p != argv + argc; ++p){
    24         ifstream input(*p);//创建输出流并打开文件
    25         if(input) process(input);
    26         else cerr << "couldn't open: " + string(*p) << endl;
    27         // input.close();
    28     }
    29     return 0;
    30 }

    因为 output 和 input 是局部变量,它在每个循环步中都要创建和销毁一次。当一个 fstream 对象离开其作用域时,与之对应的文件会自动关闭。在下一步循环中,它们会再次被创建。当一个 fstream 对象被销毁时,close 会自动调用。

    文件模式:

    每个流都有一个关联的文件模式,用来指出如何使用文件:

    in      以读方式打开

    out         以写方式打开

    app        每次写操作前均定位到文件末尾

    ate       打开文件后立即定位到文件末尾

    trunc       截断文件

    binary     以二进制方式进行IO

    指定文件模式有如下限制:

    1.只可以对 ofstream 或 fstream 对象设定 out 模式。

    2.只可以对 ifstream 或 fstream 对象设定 in 模式。

    3.只有当 out 也被设定时才可以设定 trunc 模式。

    4.只要 trunc 没被设定,就可以设定 app 模式。在 app 模式下,即使没有显示指定 out 模式,文件也总是以输出方式被打开。

    5.默认情况下,即使我们没有指定 trunc,以 out 模式打开的文件也会被截断。为了保留以 out 模式打开的文件内容,我们必须同时指定 app 模式,这样才会以追加的模式写到文件末尾:或者同时指定 in 模式,即打开文件同时进行读写操作。

    6.ate 和 binaty 模式可用于任何类型的文件流对象,且可以与其他任何文件模式组合使用。

    每个文件流类型都定义了一个默认的文件模式,当我们未指定文件模式时,就使用此默认模式。ifsream 关联的文件默认以 in 模式打开,ofstream 关联的文件默认以 out 模式打开,fstream 关联的文件默认以 in 和 out 模式打开。

    对流的操作:

    对输入流操作:seekg()与tellg()
    对输出流操作:seekp()与tellp()


    下面以输入流函数为例介绍用法:
    seekg() 是对输入文件定位,它有两个参数:第一个参数是偏移量,第二个参数是基地址。
    对于第一个参数,可以是正负数值,正的表示向后偏移,负的表示向前偏移。而第二个参数可以是:
    ios::beg:表示输入流的开始位置
    ios::cur:表示输入流的当前位置
    ios::end:表示输入流的结束位置
    tellg() 函数不需要带参数,它返回当前定位指针的位置,也代表着输入流的大小。

     1 #include <iostream>
     2 #include <fstream>
     3 using namespace std;
     4 
     5 const char *filename = "D:\code\c++\ac27.text";//该文件中存储了abcd四个字符
     6 
     7 int main(void){
     8     long l, m;
     9     ifstream in(filename, ios::in | ios::binary | ios::ate);//加了ate参数,此时get指针在文件末尾('')的下一个位置
    10     l = in.tellg();
    11     in.seekg(0, ios::end);//将get指针移动到文件末尾下一个位置
    12     m = in.tellg();//得到get指针当前的位置
    13     in.close();
    14     cout << l << endl;//输出6
    15     cout << "size of " << filename;
    16     cout << " is " << (m - 1) << " byset.
    ";//m-1为5
    17     return 0;
    18 }

    对于输出流操作:seekp()与tellp()用法是一样的。

  • 相关阅读:
    多进程交替控制输出
    最长不重复子串
    const关键字的使用
    C++类的内存分布
    shell编程--awk 、sed 命令介绍
    gcc 6.0编译opencv出错
    NTP同步网络时间
    树莓派配置RTC时钟(DS3231,I2C接口)
    浏览器播放rtmp流
    nginx配置hls
  • 原文地址:https://www.cnblogs.com/geloutingyu/p/8269485.html
Copyright © 2020-2023  润新知