C++ 提供以下类来执行文件的字符输出和输入:

  • ofstream:写入文件的流类
  • ifstream:从文件中读取的流类
  • fstream:流类以读取和写入文件。

表5: 文件读写模式

读写模式 意义
ios::in 打开输入操作(ifstream的默认模式)。
ios::out 打开以进行输出操作(ofstream的默认模式)。
ios::binary 以二进制模式打开。
ios::ate 在文件末尾设置初始位置。 如果未设置此标志,则初始位置是文件的开头。
ios::app 所有输出操作都在文件末尾执行,将内容附加到文件的当前内容。
ios::trunc 如果打开文件以进行输出操作并且它已经存在,则删除其先前的内容并用新的内容替换。

表6:ios_base 标识的组合意义

ios_base 标识 意义 C模式
in 读取 (文件必须存在) “r”
out 清空之后改写 (有必要才产生) “w”
out | trunc 清空之后改写 (有必要才产生) “w”
out | app 添加 (有必要才产生) “a”
in | out 读和写: 最初位置在起始点 (文件必须存在) “r + ”
in | out | trunc 先清空, 再读写 (有必要才产生) “w+”

ofstream:写入文件的流类

例8:输出文本文件

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

#include <iostream>

#include <iomanip>

#include <vector>

#include <string>

#include <fstream>

int main()

{

    std::vector<std::string> fruit{ "火龙果","梨" };

    std::vector<double> price{ 3.02,4.51 };

    //使用输出至显示器

    std::cout << "水果名 单价\n" << std::setiosflags(std::ios::left);

    for (int i = 0; i < 2; ++i)

    {

        std::cout << std::setw(8) << fruit[i];

        std::cout << std::setw(6) << price[i];

        std::cout << std::endl;

    }

    // 使用文件输出流类ofstream的文件对象fout将数据输出到文本文件price.txt

    std::ofstream fout; //文件输出流类ofstream对象fout需要程序员自己定义

    fout.open("price.txt",std::ios::out);//打开文件price.txt,如文件不存在则创建新文件

    fout << "水果名 单价\n" << std::setiosflags(std::ios::left);

    for (int i = 0; i < 2; ++i)

    {

        fout << std::setw(8) << fruit[i];

        fout << " ";

        fout << std::setw(6) << price[i];

        fout << std::endl;

    }

    fout.close(); //关闭所打开的文件price.txt

    return 0;

}

结果:

水果名 单价
火龙果  3.02
梨      4.51

例9:输出二进制文件

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

#include <iostream>

#include <iomanip>

#include <string.h>

#include <fstream>

int main()

{

    char *fruit[] = { "火龙果","梨" };

    double price[] = { 3.02,4.51 };

    char str[7];

    //使用文件对象fout将数据输出到二进制文件price.dat

    std::ofstream fout; //文件输出流类ofstream对象fout需要程序员自己定义

    fout.open("price.dat",std::ios::out|std::ios::binary);//以二进制模式打开文件price.dat,如文件不存在则创建新文件

    for (int i = 0; i < 2; ++i)

    {

        strcpy(str,fruit[i]);

        fout.write(str,sizeof(str));//输出水果名

        fout.write((char*)(&price[i]),sizeof(double));//输出价格

    }

    fout.close(); //关闭所打开的文件price.dat

    return 0;

}

ifstream:从文件中读取的流类

例10:输入文本文件

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

#include <iostream>

#include <fstream>

int main()

{

    char fruit[20];

    double price;

    std::ifstream fin; //使用文件输入流类ifstream的文件对象fin从文本文件price.txt中输入数据

    fin.open("price.txt"); //打开文本文件

    if(fin.is_open()==false) //检查打开文件是否成功

        std::cout<<"打开文件price.txt失败"<<std::endl;

    else

    {

        fin.getline(fruit,19); //读出标题行

        std::cout<<fruit<<std::endl; //显示所读出的标题行,显示结果:水果名称单价

        for(int i=0;i<2;++i)

        {

            fin>>fruit>>price; //从文件price.txt中读取水果名称和单价

            std::cout<<fruit<<","<<price<<std::endl; //显示水果名称和单价,验证输入结果

        }

        fin.close(); //关闭所打开的文件price.txt

    }

    return 0;

}

结果:

水果名 单价
火龙果,3.02
梨,4.51

例11:输入二进制文件

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

#include <iostream>

#include <iomanip>

#include <fstream>

int main()

{

    char name[20];

    double num;

    std::ifstream fin;

    fin.open("price.dat",std::ios::in |std::ios::binary);

    for (int i = 0; i < 2; ++i)

    {

        fin.read(name,7);

        fin.read((char*)(&num),8);

        std::cout<<name<<" "<<num<<std::endl;

    }

    fin.close(); //关闭所打开的文件price.dat

    return 0;

}

结果:

火龙果 3.02
梨 4.51

表7:检查流的特定状态

成员函数 意义
good 检查是否没有发生错误,
eof 检查是否到达了文件末尾
fail 检查是否发生了可恢复的错误
bad 检查是否已发生不可恢复的错误

例12:检查输入文件状态

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

#include <iostream>

#include <fstream>

int main()

{

    char ch;

    std::ifstream fin; //使用文件输入流类ifstream的文件对象fin从文本文件price.txt中输入数据

    fin.open("price.txt"); //打开文本文件

    while(true)

    {

        fin.get(ch); //从文件price.txt中每次读取一个字符

        //eof的返回值:true-文件已结束,false-文件未结束

        //good的返回值:true-文件正常,false-文件已损坏

        if(fin.eof()==true||fin.good()==false)

            break; //结束文件输入

        std::cout <<ch; //显示所读出的字符ch

    }

    fin.close(); //关闭所打开的文件price.txt

    return 0;

}

结果:

水果名 单价
火龙果   3.02
梨       4.51

fstream:流类以读取和写入文件

表 8: 文件定位标志

模式标志 描述
ios::beg 从文件头开始计算偏移量
ios::end 从文件末尾开始计算偏移量
ios::cur 从当前位置开始计算偏移量

随机读写文件

打开文件后,文件对象与外存文件建立起关联关系。此时,文件对象内部将保存当前读写数据的位置信息。该位置信息保存在被称作文件指针的数据成员中。

文件输入流对象包含一个读文件指针,文件输出流对象包含一个写文件指针,而文件输入/输出流对象则分别包含一个读文件指针和一个写文件指针。

更多推荐