C++文件操作之打开方式、随机存取、缓冲区及流状态

此课件及源代码来自B站up主:码农论坛,该文章仅作为本人学习笔记使用。

1、文件操作-文件打开模式(方式)

如果文件不存在,各种模式都会创建文件。

ios::out             1)会截断文件;2)可以用seekp()移动文件指针。

ios:trunc          1)会截断文件;2)可以用seekp()移动文件指针。

ios::app            1)不会截断文件;2)文件指针始终在文件未尾,不能用seekp()移动文件指针。

ios::ate             打开文件时文件指针指向文件末尾,但是,可以在文件中的任何地方写数据。

ios::in               打开文件进行读操作,即读取文件中的数据。

ios::binary        打开文件为二进制文件,否则为文本文件。

注:ate是at end的缩写,trunc是truncate(截断)的缩写,app是append(追加)的缩写。

2、文件操作-随机存取

一、fstream类

fstream类既可以读文本/二进制文件,也可以写文本/二进制文件。

fstream类的缺省模式是ios::in | ios::out,如果文件不存在,则创建文件;但是,不会清空文件原有的内容。

普遍的做法是:

1)如果只想写入数据,用ofstream;如果只想读取数据,用ifstream;如果想写和读数据,用fstream,这种情况不多见。不同的类体现不同的语义。

2)在Linux平台下,文件的写和读有严格的权限控制。(需要的权限越少越好)

二、文件的位置指针

对文件进行读/写操作时,文件的位置指针指向当前文件读/写的位置。

很多资料用“文件读指针的位置”和“文件写指针的位置”,容易误导人。不管用哪个类操作文件,文件的位置指针只有一个。

1)获取文件位置指针

ofstream类的成员函数是tellp()ifstream类的成员函数是tellg()fstream类两个都有,效果相同。

std::streampos tellp();

std::streampos tellg();

2)移动文件位置指针

ofstream类的函数是seekp()ifstream类的函数是seekg()fstream类两个都有,效果相同。

方法一:

std::istream & seekg(std::streampos _Pos); 

fin.seekg(128);   // 把文件指针移到第128字节。

fin.seekp(128);   // 把文件指针移到第128字节。

fin.seekg(ios::beg) // 把文件指针移动文件的开始。

fin.seekp(ios::end) // 把文件指针移动文件的结尾。

方法二:

std::istream & seekg(std::streamoff _Off,std::ios::seekdir _Way);

在ios中定义的枚举类型:

enum seek_dir {beg, cur, end};  // beg-文件的起始位置;cur-文件的当前位置;end-文件的结尾位置。

fin.seekg(30, ios::beg);    // 从文件开始的位置往后移30字节。

fin.seekg(-5, ios::cur);     // 从当前位置往前移5字节。

fin.seekg( 8, ios::cur);     // 从当前位置往后移8字节。

fin.seekg(-10, ios::end);   // 从文件结尾的位置往前移10字节。

三、随机存取

随机存取是指直接移动文件的位置指针,在指定位置读取/写入数据。

示例:

#include <iostream>
#include <fstream>  // fstream类需要包含的头文件。
using  namespace std;

int main()
{
      string filename = R"(D:\data\txt\test.txt)";
      fstream fs;
      fs.open(filename, ios::in | ios::out);

      if (fs.is_open() == false)
      {
            cout << "打开文件" << filename << "失败。\n";  return 0;
      }

      fs.seekg(26);    // 把文件位置指针移动到第26字节处。
      fs << "我是一只傻傻的小菜鸟。\n";

      /*string buffer;
      while (fs >> buffer)
      {
            cout << buffer << endl;
      }*/

      fs.close();      // 关闭文件,fs对象失效前会自动调用close()。

      cout << "操作文件完成。\n";
}

3、文件操作-缓冲区及流状态

一、文件缓冲区

文件缓冲区(缓存)是系统预留的内存空间,用于存放输入或输出的数据。

根据输出和输入流,分为输出缓冲区和输入缓冲区。

注意,在C++中,每打开一个文件,系统就会为它分配缓冲区。不同的流,缓冲区是独立的

程序员不用关心输入缓冲区,只关心输出缓冲区就行了。

在缺省模式下,输出缓冲区中的数据满了才把数据写入磁盘,但是,这种模式不一定能满足业务的需求。

输出缓冲区的操作:

1flush()成员函数

刷新缓冲区,把缓冲区中的内容写入磁盘文件。

2endl

换行,然后刷新缓冲区。

3unitbuf

fout << unitbuf;

设置fout输出流,在每次操作之后自动刷新缓冲区。

4nounitbuf

fout << nounitbuf;

设置fout输出流,让fout回到缺省的缓冲方式。

二、流状态

流状态有三个:eofbit、badbit和failbit,取值:1-设置;或0-清除。

当三个流状成都为0时,表示一切顺利,good()成员函数返回true。

1)eofbit

当输入流操作到达文件未尾时,将设置eofbit。

eof()成员函数检查流是否设置了eofbit。

2)badbit

无法诊断的失败破坏流时,将设置badbit。(例如:对输入流进行写入;磁盘没有剩余空间)。

bad()成员函数检查流是否设置了badbit。

3)failbit

当输入流操作未能读取预期的字符时,将设置failbit(非致命错误,可挽回,一般是软件错误,例如:想读取一个整数,但内容是一个字符串;文件到了未尾)I/O失败也可能设置failbit。

fail()成员函数检查流是否设置了failbit。

4)clear()成员函数清理流状态。

5)setstate()成员函数重置流状态。

示例1:

#include <iostream>
#include <fstream>          // ofstream类需要包含的头文件。
#include <unistd.h>
using  namespace std;

int main()
{
  ofstream fout("/oracle/tmp/bbb.txt");   // 打开文件。
  fout << unitbuf;

  for (int ii = 0; ii < 1000; ii++)  // 循环1000次。
  {
    fout << "ii=" << ii << ",我是一只傻傻傻傻傻傻傻傻傻傻傻傻傻傻的鸟。\n";
    //fout.flush();      // 刷新缓冲区。
    usleep(100000);    // 睡眠十分之一秒。
  }

  fout.close();  // 关闭文件。
}

示例2:

#include <iostream>
#include <fstream>  // ifstream类需要包含的头文件。
#include <string>     // getline()函数需要包含的头文件。
using  namespace std;

int main()
{
      ifstream fin(R"(D:\data\txt\test.txt)", ios::in);

      if (fin.is_open() == false) {
            cout << "打开文件" << R"(D:\data\txt\test.txt)" << "失败。\n";  return 0;
      }

      string buffer;
      /*while (fin >> buffer) {
            cout << buffer << endl;
      }*/

      while (true) {
            fin >> buffer;
            cout << "eof()=" << fin.eof() << ",good() = " << fin.good() << ", bad() = " << fin.bad() << ", fail() = " << fin.fail() << endl;

            if (fin.eof() == true) break;

            cout << buffer << endl;
      }

      fin.close();     // 关闭文件,fin对象失效前会自动调用close()。
}

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值