C++之文件输入/输出流类解读

 更新时间:2023年08月07日 08:36:33   作者:陨星落云  
这篇文章主要介绍了C++之文件输入/输出流类,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

文件输入/输出流类

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:输出文本文件

#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:输出二进制文件

#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:输入文本文件

#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:输入二进制文件

#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:检查输入文件状态

#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从当前位置开始计算偏移量

随机读写文件

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

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

通常情况下,打开文件后文件对象的读/写指针都定位于文件头的位置。

每执行一次读/写操作,读/写指针将自动后移,移到下一次读/写数据的位置。这就是文件的顺序读/写。

可以调用函数成员seekg和tellg来移动或读取读文件指针的位置,调用函数成员seekp知和tellp来移动或读取写文件指针的位置。

程序员通过移动读/写指针,可实现对文件的随机读写。

这4个与文件指针相关函数的原型如下:

文件指针相关函数描述
istream& seekg(long bytes,ios::seek dir origin )移动读文件指针
long tellg()返回当前读文件指针的位置
ostream& seekp(long bytes,ios::seek_dir origin )移动写文件指针
long tellp()返回当前写文件指针的位置

例13:随机读写文件

#include <iostream>
#include <fstream>
int main()
{
    char fruit[20];
    double price;
    std::ifstream fin; 
    fin.open("price.dat"); //打开二进制文件
    if(fin.is_open()==false) //检查打开文件是否成功
        std::cout<<"打开文件price.dat失败"<<std::endl;
    else
    {
        for(int i=0;i<2;++i)
        {
            fin.read(fruit,7); 
            //std::cout << fin.tellg() << '\n'; 
            fin.read((char*)&price,8);
            std::cout << fin.tellg() << '\n'; //当前读文件指针的位置
            std::cout<<fruit<<","<<price<<std::endl; //显示水果名称和单价,验证输入结果
        }
        fin.seekg(-30L,std::ios::end);//从文件尾向前(即往回)移动两行(一行有15个字节)
        fin.read(fruit,7); 
        std::cout<<fruit<<std::endl;
        fin.seekg(8L,std::ios::cur);//当前位置开始向后移动7个字节
        fin.read(fruit,7); 
        std::cout<<fruit<<std::endl;
        fin.close(); //关闭所打开的文件price.dat
    }
    return 0;
}

结果:

15
火龙果,3.02
30
梨,4.51
火龙果

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 如何在C语言的宏中使用类型关键字

    如何在C语言的宏中使用类型关键字

    如何在C语言的宏中使用类型关键字呢?以下是实现方法。需要的朋友可以过来参考下,希望对大家有所帮助
    2013-10-10
  • C++快速排序的分析与优化详解

    C++快速排序的分析与优化详解

    这篇文章主要介绍了C++快速排序的分析与优化,非常经典的算法,分析也较为详尽,需要的朋友可以参考下
    2014-08-08
  • C++实现list增删查改模拟的示例代码

    C++实现list增删查改模拟的示例代码

    本文主要介绍了C++实现list增删查改模拟,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-12-12
  • delete[] p->elems和free(p->elems)区别介绍

    delete[] p->elems和free(p->elems)区别介绍

    delete[]和free()都是释放内存的函数,但它们具有不同的使用方法和适用情况,这篇文章主要介绍了delete[] p->elems和free(p->elems)有什么区别,需要的朋友可以参考下
    2023-04-04
  • 利用C语言实现2048小游戏的方法

    利用C语言实现2048小游戏的方法

    2048是比较流行的一款数字游戏,相信对大家来说都不陌生,这篇文章给大家分享了利用C语言实现2048小游戏的方法,对大家学习理解C语言具有一定的参考借鉴价值,有需要的朋友们下面来一起看看吧。
    2016-10-10
  • C++实现校园导游系统

    C++实现校园导游系统

    这篇文章主要为大家详细介绍了C++实现校园导游系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • C++异常捕捉与处理的深入讲解

    C++异常捕捉与处理的深入讲解

    这篇文章主要给你大家介绍了关于C++异常捕捉与处理的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-10-10
  • vs2022 qt环境搭建调试的方法步骤

    vs2022 qt环境搭建调试的方法步骤

    最近net6和vs2022发布,本文就详细的介绍一下vs2022 qt环境搭建调试的方法步骤,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-12-12
  • C++回溯算法中子集问题分析探讨

    C++回溯算法中子集问题分析探讨

    回溯法是一种选优搜索法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为回溯点
    2023-03-03
  • 解析c++中的默认operator=操作的详解

    解析c++中的默认operator=操作的详解

    本篇文章是对c++中的默认operator=操作的应用进行了详细的分析介绍。需要的朋友参考下
    2013-05-05

最新评论