文件流的系统学习 ( 一 )

概述

计算机中有两种常见存储方式:

  • 临时存储:变量和数组
  • 永久存储:文件
    • 保存大量的数据
    • 存储在二级存储设备中
      • Magnetic disks
      • Optical disks
      • Tapes

文件的基本概念
C++文件 (file) 分为两类:二进制文件文本文件
文本文件由字符序列组成,也称ASCII文件。在文本文件中存取的最小信息单位为字符 (character) 。
二级制文件中存取的最小信息单位为字节 (Byte) 。
C++把每一个文件都看作一个有序的字节流,每一个文件或者以文件结束符 (EOF) 结束,或者在特定的字节号处结束。

下面我们具体解释一些重点概念:

Bits (二进制位)

  • 0 or 1
  • 计算机支持的最小数据项
    • 计算机电路执行位处理
    • 所有数据项最终由位组成

Characters (字符)

  • 数字,字母和专门的符号称为字符
  • 能够在特定计算机上用来编写程序和代表数据项的所有字符的集合称为 " 字符集 "
  • Char以字节形式存储 (8 bits)

Fields (字段或数据项)

  • 由字符组成
  • 代表一定的含义

Records (记录)

  • 由多个字段组成
  • 在C++中表现为:类
  • 记录的关键字:A record key is a field unique to each record
    在这里插入图片描述

C++の流类库

当打开一个文件时,该文件就和某个流关联起来了。对文件进行读写实际上受到一个文件定位指针 (file position pointer) 的控制。
输入流指针也称作读指针,每一次提取操作将从读指针当前所指位置开始,每次提取操作自动将读指针向文章尾移动。
输出流指针也称写指针,每次插入操作将从写指针当前位置开始,每次插入操作自动将写指针向文章尾移动。

输入流:数据从某个载体或设备传送到内存缓冲区变量
输出流:数据从内存传送到某个载体或设备中

程序用 统一了对各种计算机设备和文件的操作形式

在这里插入图片描述
其中,basic_streambuf不是basic_ios的派生类,而是一个独立的类,basic_ios有一个保护访问限制的指针指向它
类basic_streambuf的作用是管理流的缓冲区

iostream预先定义了四个标准流对象:

含义 对象 备注 所属类 默认设备
标准输入 cin istream类 键盘
标准输出 cout 缓冲区暂存后标准输出 ostream类 显示器
标准错误输出 cerr 未缓冲 ostream类 显示器
标准错误输出 clog 缓冲 ostream类 显示器

文件处理

包含头文件:#include<fstream>

  • 包括三种类模板的定义
basic_ifstream // for file input
basic_ofstream // for file output
basic_fstream  // for file input and output
  • 提供了处理字符流的模板特化
    • ifstream:从文件中读入字符 (读文件)
    • ofstream:向文件中输出字符 (写文件)
    • fstream:支持文件中字符的输入和输出
    • 生成这些流类模板特化的对象,即可打开文件
    • 程序和文件之间通过流对象交互

创建文件

输出流文件

  • 创建ofstream文件 (对象)
    • 构造函数:ofstream(const char* filename,int mode)
      filename:文件名由文件的主名和扩展名两部分组成
      mode
      ios::out //缺省模式,覆盖文件中已有数据
      ios::app //向文件末尾添加数据
ofstream outClientFile("clients.dat",ios::out);
  • 对于已创建的文件对象,使用成员函数打开文件
    • 与构造函数参数相同:(const char* filename,int mode)
ofstream outClientFile;
outClientFile.open("client.dat");

输入流文件

  • 创建ifstream对象
    • 构造函数:ifstream(const char* filename,int mode)
      filename:文件名由文件的主名和扩展名两部分组成
      mode
      ios::in //缺省模式,只能从文件读取数据,最小权限原则
      ios::app //向文件末尾添加数据
ifstream inClientFile("clients.dat",ios::in);
  • 对于已经存在的ifstream对象,使用成员函数打开文件
ifstream inClientFile;
inClientFile.open("clients.dat", ios::in);
文件打开方式 含义
ios::in 以输入 (读) 方式打开文件
ios::out 以输入 (写) 方式打开文件
ios::app 打开一个文件使新的内容添加在文件的末尾
ios::ate 打开一个文件使新的内容添加在文件的末尾,但在下次添加时,写在当前位置处
ios::trunc 若文件存在,则清楚文件所有内容;若文件不存在,则创建新文件
ios::binary 以二进制方式打开文件,缺省时以文本方式打开文件
ios::nocreate 打开一个已有文件,若该文件不存在,则打开失败
ios::noreplace 若打开的文件已经存在,则打开失败

in:(从文件读取) 打开方式只要含in,则在指定的文件不存在的情况下返回失败。在打开为输入输出方式时(同时使用inout),编程应注意判断是否失败,失败时不可再写入文件。

out:(写入文件) 如文件不存在,则建立新文件,如文件存在且未设定app,in,则文件清空。

trunc:(打开文件,并清空它) 文件不存在时则建立新文件 ,与out默认操作相同。但与in配合时,文件不存在则返回失败。

app:(写入文件,添加在末尾) 原文件内容保留,新数据写在尾部。

ate: (打开文件,文件指针在文件尾) 文件指针可以移动,即新数据可写到任何位置。文件是否清空由其它标识决定。

注意:

  • truck/app/ate最好配合out,in等一起用。因为不同的C++平台 ,要求不同,一起用保证不会出错。
  • binary标识以二进制方式打开文件。同时使用out时,如文件不存在 ,则建立新文件,并且新文件能用,不必清除状态字。

文件打开方式由在ios类中定义的公有枚举成员决定:

enum open_mode{
    in=0x01,
    out=0x02,
    ate=0x04,
    app=0x08,
    trunc=0x10
    binary=0x80
};
// Example
fstream iofile;   //既输入又输出用
iofile.open("myfile.txt",ios::in||ios:out);

三个文件流类都重载了一个带默认参数的构造函数:

ifstream::ifstream(const char*,int =ios::in,int =filebuf::openprot);
ofstream::ofstream(const char*,int =ios::out,int =filebuf::openprot);
fstream::fstream(const char*,int,int =filebuf::openprot);

文件流类定义了打开文件的成员函数,在文件流对象和磁盘文件名之间建立联系:

void ifstream::open(const char*,int =ios::in,int =filebuf::openprot);
void ofstream::open(const char*,int =ios::out,int =filebuf::openprot);
void fstream::open(const char*,int,int =filebuf::openprot);

其中,第三个参数为指定打开文件的保护方式,一般取默认值

打开文件时应该判断是否成功
若成功,文件流对象的值 (ta的地址) 非零,不成功为0 (NULL)

fstream iofile("myfile.txt",ios::in|ios::out);
if (!iofile) { //!为重载的运算符
    cout<<"文件 myfile.txt 打开失败\n";
    return -1;
}

文件的打开与关闭

  • 声明一个文件流对象 (又被称为内部文件)
    • ifstream ifile; // 输入用
    • ofstream ofile; // 输出用
    • fstream iofile; // 输入输出用
  • 使用文件流对象的成员函数打开一个磁盘文件
    • iofile.open("myfile",ios::in||ios::out);
  • 使用提取和插入运算符对文件进行读写操作,或使用成员函数进行读写
  • 关闭文件
    三个文件流类各有一个关闭文件的成员函数:
    • void ifstream::close();
    • void ofstream::close();
    • void fstream::close();

关闭文件时,系统把该文件相关联的文件缓冲区中的数据写到文件中,保证文件的完整,收回与该文件相关的内存空间,可供再分配。把磁盘文件名与文件流对象之间的关联断开,可防止误操作修改了磁盘文件。如果要对文件再操作,必须重新打开。
关闭文件并没有取消文件流对象,该文件流对象又可与其他磁盘文件建立联系。文件流对象在程序结束时,或ta的生命期结束时,由析构函数撤消。ta会同时释放内部分配的预留缓冲区。


实例

向文件中写数据

#include<iostream>
using std::cerr;
using std::cin;
using std::cout;
using std::endl;
using std::ios;

#include<fstream>
using std::ofstream;

#include<cstdlib>
using std::exit;

int main()
{
	ofstream outClientFile("clients.dat",ios::out);
	//创建ofstream对象,打开文件
	if (!outClientFile) {  //重载!,返回true表示文件打开成功
		cerr<<"File could not be opened.\n";
		exit(1);
	}

	cout<<"Enter the account, name, and balance.\n"
		<<"Enter end-of-file to and input.\n? ";

	int account;
	char name[30];
	double balance;
	while (cin>>account>>name>>balance) {  
	//重载operator void *,当用户输入结束符时返回一个空指针
		outClientFile<<account<<" "<<name<<" "<<balance<<endl;
		//使用<<向文件中写入数据
		cout<<"? ";
	}

	return 0;
	//ofstream的析构函数被隐式调用,关闭文件
}

在这里插入图片描述在这里插入图片描述

从文件中读数据

#include<iostream>
using std::cerr;
using std::cout;
using std::endl;
using std::fixed;
using std::ios;
using std::left;
using std::right;
using std::showpoint;

#include<fstream>
using std::ifstream;

#include<iomanip>
using std::setw;
using std::setprecision;

#include<string>
using std::string;

#include<cstdlib>
using std::exit;

void outputLine(int account,const string name,double balance) 
{
	cout<<left<<setw(10)<<account<<setw(13)<<name
		<<setw(7)<<setprecision(2)<<right<<balance<<endl;
}

int main()
{
	ifstream inClientFile("clients.dat",ios::in);
	//创建ifstream对象,打开文件
	if (!inClientFile) {  //重载!,返回true表示文件打开成功
		cerr<<"File could not be opened.\n";
		exit(1);
	}

	int account;
	char name[30];
	double balance;

	cout<<left<<setw(10)<<"Account"
		<<setw(13)<<"Name"<<"Balance"<<endl<<fixed<<showpoint;
	while (inClientFile>>account>>name>>balance)  
	//重载operator void *,当遇到文件结束符时返回一个空指针
		outputLine(account,name,balance);

	return 0;
	//ifstream的析构函数被隐式调用,关闭文件
}

在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章