zoukankan      html  css  js  c++  java
  • C++文件读写详解(ofstream,ifstream,fstream)

    这里主要是讨论fstream的内容:

    1 #include <fstream>  
    2 ofstream         //文件写操作 内存写入存储设备   
    3 ifstream         //文件读操作,存储设备读区到内存中  
    4 fstream          //读写操作,对打开的文件可进行读写操作

    1、打开文件

    在fstream类中,成员函数open()实现打开文件的操作,从而将数据流和文件进行关联,通过ofstream,ifstream,fstream对象进行对文件的读写操作

    函数:open()

     1 public member function  
     2   
     3 void open ( const char * filename,  
     4             ios_base::openmode mode = ios_base::in | ios_base::out );  
     5   
     6 void open(const wchar_t *_Filename,  
     7         ios_base::openmode mode= ios_base::in | ios_base::out,  
     8         int prot = ios_base::_Openprot);
     9 /*
    10 参数:filename   操作文件名
    11            mode        打开文件的方式
    12            prot         打开文件的属性    //基本很少用到,在查看资料时,发现有两种方式
    13 
    14 */

    打开文件的方式在IOS类(流式I/O的基类)中定义,有如下几种方式:

    ios::in
    为输入(读)而打开文件,文件不存在则创建(ifstream)默认的打开方式

    ios::out

    为输出(写)而打开文件,文件不存在则创建,若文件已存在则清空原内容

    (ofstream默认的打开方式)

    ios::ate 
    文件打开时,指针在文件最后。可改变指针的位置,常和in、out联合使用

    ios::app

    供写使用,文件不存在则创建,若文件已存在则在原文件内容后写入新的内容,

    指针位置总在最后

    ios::trunc
    在读写前,先将文件长度截断为0(默认)

    ios::nocreate
    文件不存在时产生错误,常和in或app联合使用

    ios::noreplace
    文件存在时产生错误,常和out联合使用

    ios::binary
    二进制格式文件

    这些方式是能够以“或”运算(“|”)的方式进行组合使用。

    文件保护方式选择项

    filebuf::openprot
    默认的兼容共享方式

    filebuf::sh_none
    独占,不共享

    filebuf::sh_read
    读共享

    filebuf::sh_write
    写共享

    很多程序中,可能会碰到ofstream out("Hello.txt"), ifstream in("..."),fstream foi("...")这样的的使用,并没有显式的去调用open()函数就进行文件的操作,直接调用了其默认的打开方式,因为在stream类的构造函数中调用了open()函数,并拥有同样的构造函数,所以在这里可以直接使用流对象进行文件的操作,默认方式如下:

    1 ofstream out("...", ios::out);  
    2 ifstream in("...", ios::in);  
    3 fstream foi("...", ios::in|ios::out);  

    2.关闭文件

    当文件读写操作完成之后,我们必须将文件关闭以使文件重新变为可访问的。成员函数close(),它负责将缓存中的数据排放出来并关闭文件,这个函数一旦被调用,原先的流对象就可以被用来打开其它的文件,这个文件也就可以重新被其它的进程所访问。为防止流对象被销毁时还联系着打开的文件,析构函数将会自动调用关闭函数close。

    3.文本文件的读写

    类ofstream, ifstream 和fstream 是分别从ostream, istream 和iostream 中引申而来的。这就是为什么 fstream 的对象可以使用其父类的成员来访问数据。一般来说,我们将使用这些类与同控制台(console)交互同样的成员函数(cin 和 cout)来进行输入输出。如下面的程序所示,我们使用重载的插入操作符<<和读出操作符>>:

     1 #include "iostream"
     2 #include<fstream>
     3 using namespace std;
     4 void main()
     5 {
     6     fstream f("d:\\try.txt", ios::out);//供写使用,文件不存在则创建,存在则清空原内容
     7     f << 1234 << ' ' << 3.14 << 'A' << "How are you"; //写入数据
     8     f.close();//关闭文件以使其重新变为可访问,函数一旦调用,原先的流对象就可以被用来打开其它的文件
     9     f.open("d:\\try.txt", ios::in);//打开文件,供读
    10     int i;
    11     double d;
    12     char c;
    13     char s[20];
    14     f >> i >> d >> c;               //读取数据
    15     f.getline(s, 20);
    16     cout << i << endl;             //显示各数据
    17     cout << d << endl;
    18     cout << c << endl;
    19     cout << s << endl;
    20     f.close();
    21 }
    状态标志符的验证(Verification of state flags)
    • bad()

      如果在读写过程中出错,返回 true 。例如:当我们要对一个不是打开为写状态的文件进行写入时,或者我们要写入的设备没有剩余空间的时候。

    • fail()

      除了与bad() 同样的情况下会返回 true 以外,加上格式错误时也返回true ,例如当想要读入一个整数,而获得了一个字母的时候。

    • eof()

      如果读文件到达文件末尾,返回true。

    • good()

      这是最通用的:如果调用以上任何一个函数返回true 的话,此函数返回 false 。

    要想重置以上成员函数所检查的状态标志,你可以使用成员函数clear(),没有参数。

    获得和设置流指针(get and put stream pointers)

      所有输入/输出流对象(i/o streams objects)都有至少一个流指针:

    • ifstream, 类似istream, 有一个被称为get pointer的指针,指向下一个将被读取的元素。
    • ofstream, 类似 ostream, 有一个指针 put pointer ,指向写入下一个元素的位置。
    • fstream, 类似 iostream, 同时继承了get 和 put
    • tellg() 和 tellp()

     这两个成员函数不用传入参数,返回pos_type 类型的值(根据ANSI-C++ 标准) ,就是一个整数,代表当前读出流get指针的位置 (用tellg) 或写入流put指针的位置(用tellp)。

    • seekg() 和seekp()

      这对函数分别用来改变流指针get 和put的位置。两个函数都被重载为两种不同的原型:

    (一)

    1 seekg ( pos_type position );
    2 seekp ( pos_type position );
    3 /*
    4 使用这个原型,流指针被改变为指向从文件开始计算的一个绝对位置。要求传入的参数类型与函数 tellg 和tellp 的返回值类型相同。
    5 */

    (二)

    1 seekg ( off_type offset, seekdir direction );
    2 seekp ( off_type offset, seekdir direction );
    3 /*
    4 该原型有两个参数:第一个参数是偏移量,
    5 第二个参数是基地址。它可以是: 6 ios::beg 从流开始位置计算的位移 7 ios::cur 从流指针当前位置开始计算的位移 8 ios::end 从流末尾处开始计算的位移 9 */

    流指针 get 和 put 的值对文本文件(text file)和二进制文件(binary file)的计算方法都是不同的,因为文本模式的文件中某些特殊字符可能被修改。由于这个原因,建议对以文本文件模式打开的文件总是使用seekg 和 seekp的第一种原型,而且不要对tellg 或 tellp 的返回值进行修改。对二进制文件,你可以任意使用这些函数,应该不会有任何意外的行为产生。

    以下程序使用这些函数来获得一个二进制文件的大小:

    // obtaining file size  
       #include <iostream>  
       #include <fstream>  
       using namespace std;
       const char * filename = "test.txt";  
         
       int main () {  
           long l,m;  
           ifstream in(filename, ios::in|ios::binary);  
           l = in.tellg();  //当前get流指针的位置
           in.seekg (0, ios::end); //基地址为文件结束处,偏移地址为0,于是指针定位在文件结束处
           m = in.tellg();  //再次获取当前get流指针的位置
           in.close();  
           cout << "size of " << filename;  
           cout << " is " << (m-l) << " bytes.\n";  
           return 0;  
       }  
        
      //结果:  
      size of example.txt is 2422 bytes.  

    4.二进制文件

     在二进制文件中,使用<< 和>>,以及函数(如getline)来操作符输入和输出数据,没有什么实际意义,虽然它们是符合语法的。

      文件流包括两个为顺序读写数据特殊设计的成员函数:write 和 read。第一个函数 (write) 是ostream 的一个成员函数,都是被ofstream所继承。而read 是istream 的一个成员函数,被ifstream 所继承。类 fstream 的对象同时拥有这两个函数。它们的原型是:

    1 write ( char * buffer, streamsize size ); 2 read ( char * buffer, streamsize size );

    这里 buffer 是一块内存的地址,用来存储或读出数据。参数size 是一个整数值,表示要从缓存(buffer)中读出或写入的字符数。

     1 // reading binary file  
     2 #include <iostream>  
     3 #include <fstream>  
     4 using namespace std;
     5 
     6 const char * filename = "test.txt";
     7 
     8 int main() {
     9     char * buffer;
    10     long size;
    11     ifstream in(filename, ios::in | ios::binary | ios::ate);
    12     size = in.tellg();
    13     in.seekg(0, ios::beg);
    14     buffer = new char[size];
    15     in.read(buffer, size);
    16     in.close();
    17     for (int i = 0; i < size; i++)
    18     {
    19         if (buffer[i] != '\0')
    20             cout << buffer[i];
    21     }
    22     cout << endl;
    23     delete[] buffer;
    24     return 0;
    25 }
    26 /*
    27 运行结果:
    28 This is test!
    29 My name is Mengmeng
    30 */

    5.逐行读取写入txt文件

    写入:

     1 #include <iostream>
     2 #include <fstream>
     3 using namespace std;
     4 void main()
     5 {
     6     ofstream in;
     7 in.open("com.txt",ios::trunc); //ios::trunc表示在打开文件前将文件清空,由于是写入,文件不存在则创建
     8 int i;
     9 char a='a';
    10 for(i=1;i<=26;i++)//将26个数字及英文字母写入文件
    11 {
    12    if(i<10)
    13    {
    14     in<<"0"<<i<<"\t"<<a<<"\n";
    15     a++;
    16    }
    17    else
    18    {
    19     in<<i<<"\t"<<a<<"\n";
    20     a++;
    21    }
    22 }
    23 in.close();//关闭文件
    24 }
    25 
    26 /*
    27 运行结果:
    28 01    a
    29 02    b
    30 03    c
    31 04    d
    32 05    e
    33 06    f
    34 07    g
    35 08    h
    36 09    i
    37 10    j
    38 11    k
    39 12    l
    40 13    m
    41 14    n
    42 15    o
    43 16    p
    44 17    q
    45 18    r
    46 19    s
    47 20    t
    48 21    u
    49 22    v
    50 23    w
    51 24    x
    52 25    y
    53 26    z
    54 */

    读出:

    //第一种方法:
    #include<fstream>
    #include<string>
    #include<iostream>
    using namespace std;
    void main()
    {
        ifstream in("com.txt");
        string s;
        while (getline(in, s))//逐行读取数据并存于s中,直至数据全部读取
            cout << s.c_str() << endl;
    }
    
    /*
    getline函数是头文件string中定义的函数,包含两个参数:一是文件流的对象,二是获取后存放的变量
    */
    
    //第二种方法:
    #include <iostream>
    #include <fstream>
    using namespace std;
    void main()
    {
        char buffer[256];
        fstream out;
        out.open("com.txt", ios::in| ios::binary);
        cout << "com.txt" << " 的内容如下:" << endl;
        while (!out.eof())
        {
            out.getline(buffer, 256, '\n');//getline(char *,int,char) 表示该行字符达到256个或遇到换行就结束
            cout << buffer << endl;
        }
        out.close();
    }
    
    /*
    getline函数是istream头文件中定义的函数,它包含三个参数:一是存放的指针名称;
    二是size,表明每行的最大长度,表明当该行字符达到最大长度时结束
    三是结束的标志,即读取每一行时,遇到哪个标志结束,而该标志后面的内容当作下一行来读取。
    */
    /*
    运行结果:
    com.txt的内容如下:
    01    a
    02    b
    03    c
    04    d
    05    e
    06    f
    07    g
    08    h
    09    i
    10    j
    11    k
    12    l
    13    m
    14    n
    15    o
    16    p
    17    q
    18    r
    19    s
    20    t
    21    u
    22    v
    23    w
    24    x
    25    y
    26    z
    */

    转自:https://www.cnblogs.com/codingmengmeng/p/5545042.html

  • 相关阅读:
    Android游戏开发22:Android动画的实现J2me游戏类库用于Android开发
    android sqlite SQLiteDatabase 操作大全 不看后悔!必收藏!看后精通SQLITE (第三部分,完整代码)
    使用OGR创建dxf格式矢量数据
    mysql 数据库引擎 MyISAM InnoDB 大比拼 区别
    android sqlite SQLiteDatabase 操作大全 不看后悔!必收藏!看后精通SQLITE (第二部分)
    mysql 更改数据库引擎
    android sqlite SQLiteDatabase 操作大全 不看后悔!必收藏!看后精通SQLITE (第一部分)
    android 数字键盘使用
    MySQL Innodb数据库性能实践
    eclipse : Error while performing database login with the driver null
  • 原文地址:https://www.cnblogs.com/shenyantao/p/10660583.html
Copyright © 2011-2022 走看看