第9章 C++的文件操作 “文件”,一般是指内存以外的存储介质上一批数据的集合。C++在语言层次上提供了文件操作的一系列函数用于完成文件的操作,打开、关闭文件,读取、写入文件数据等操作。 1。字符文件与二进制文件 字符文件:又称ASCII文件或文本TEXT文件,它是以一个字节存放一个ASCII码,代表一个字符。例如,32767需要使用5个字节表示,即:

Slides:



Advertisements
Similar presentations
計算機程式語言實習課.
Advertisements

四資二甲 第三週作業 物件導向程式設計.
補充: Input from a text file
第11章 输入输出流类.
VC++系统开发 第二章 C++语言基础 河北经贸大学信息技术学院.
流类库与输入/输出 输入/输出标准流类 文件流类 串流类 输入/输出成员函数 用户自定义类型的输入/输出.
C程序设计 第10章 文 件 主讲教师: 鲁 萍 西安建筑科技大学 理学院.
微博: weibo.com/zhnitj QQ:
C++的檔案處理 綠園.
複習 struct score_Type{ int chinese,english; }; struct my_Type{
复习与总结.
计算概论 第二十一讲 文件操作 北京大学信息学院.
C++程序设计 第二讲 清华大学软件学院.
第8章 C++输入输出类层次 ffh.
刘胥影 东南大学计算机学院 面向对象程序设计1 2011~2012第3学期 刘胥影 东南大学计算机学院.
新世纪计算机专业系列教材 数据结构 C++实现 第一章 缪淮扣 顾训穰 沈 俊 编著 科 学 出 版 社.
第十一章 文件 文件概述 文件操作 文件操作实例 本章小结 作业: 练习:
授课老师:龚涛 信息科学与技术学院 2018年3月 教材: 《Visual C++程序员成长攻略》 《C++ Builder程序员成长攻略》
Object-Oriented Programming in C++ 第一章 C++的初步知识
第三章 C++中的C 面向对象程序设计(C++).
第12章 從C到C++語言 12-1 C++語言的基礎 12-2 C++語言的輸出與輸入 12-3 C++語言的動態記憶體配置
第一章 C++编程简介 丘志杰 电子科技大学 计算机学院 软件学院.
第十二章 文件 12.1 C文件概述 文件:存储在外部介质上数据的集合,是操作系统数据管理的单位 文件分类 按文件的逻辑结构: 按存储介质:
檔案 將資料存入磁碟或由磁碟取出資料的方式, 稱為檔案存取處理。 C語言的檔案處理 C++語言的檔案處理.
程式設計 博碩文化出版發行.
第八章 文件 引述 输入输出流和文件概述 文件操作 流的格式化输出 程序举例 本章小节.
第13章 输入输出流 王雪晶.
第九章 C++的I/O流库 9.1 流 9.2 磁盘文件 9.3 程序举例.
第5章 文件.
第八章 文件 引述 输入输出流和文件概述 文件操作 流的格式化输出 程序举例 本章小节.
C++语言程序设计 第十一章 流类库与输入/输出.
切換Dev c++顯示語言 工具->環境選項(V)->介面->language (Chinese TW)
10 多載函數 10.1 多載概論 多載一般函數 多載成員函數 10-3
第 14 章 輸出與輸入.
第4讲 C++程序控制结构(二) 4.1 循环结构 4.2 转向控制 4.3 综合案例分析.
第十三讲 文件流与 输出输入重载.
第14章 输入输出与文件 输入输出是指程序与外部设备交换信息 C++把输入输出看成是一个数据流 输入流:外围设备流向内存的数据
一、文件的基本概念 第十三章 文 件 所谓“文件”是指一组相关数据的有序集合。 这个数据集有一
第7章 输入/输出流 文件和I/O流概述 标准I/O流的对象及其成员函数 文件流.
手机移动设备嵌入式C++ 第七章 C++的I/O流库.
程式結構&語法.
Java變數 2014/6/24.
C++语言程序设计 C++语言程序设计 第九章 类的特殊成员 第十一组 C++语言程序设计.
第10讲 构造函数和析构函数 构造函数 析构函数 This 指针.
第3章C++面向对象程序设计 3.1 类和对象 作业1 3.2 继承和派生类 作业2 3.3 多态和虚函数 3.4 运算符重载 作业3
物件導向程式設計 CH2.
C++的檔案處理 綠園.
第11章 從C到C++語言 11-1 C++語言的基礎 11-2 C++語言的資料型態與運算子 11-3 C++語言的輸出與輸入
C++语言程序设计 C++语言程序设计 第十章 多态 第十一组 C++语言程序设计.
第十一章 IO流与文件系统 丘志杰 电子科技大学 计算机学院 软件学院.
第二章 类型、对象、运算符和表达式.
中五級電腦科 PASCAL檔案處理.
第二讲 基本数据类 型及数组等 此为封面页,需列出课程编码、课程名称和课程开发室名称。
Review 1~3.
C/C++基礎程式設計班 C++: 物件的使用、參考、重載函式 講師:林業峻 CSIE, NTU 3/28, 2015.
第1章 C++面向对象程序设计要点 1.1 函数和函数参数 1.2 输入输出   1.3 类 1.4 抽象类型和模板.
#include <iostream.h>
本节内容 指针类型.
第13章 文 件.
結構、檔案處理(Structure, File)
本章主題 C++的程式結構 資料型態與宣告 算術運算 簡易的輸入輸出指令 程式編譯(Compile)的過程與原理.
第2章 文件操作 陈哲 副教授 南京航空航天大学 计算机科学与技术学院.
第七章 文件 7.1 文件的基本概念 7.2 文件类型指针 7.3 文件的打开与关闭 7.4 文件的读/写 7.5 文件的随机读/写
基本資料型態 變數與常數 運算子 基本的資料處理 授課:ANT 日期:2014/03/03.
C++语言程序设计 C++语言程序设计 第十一章 异常处理 C++语言程序设计.
變數與資料型態  綠園.
C++程序语言设计 Chapter 14: Templates.
第二章 Java基本语法 讲师:复凡.
Introduction to the C Programming Language
C++语言程序设计 C++语言程序设计 第二章 基本数据类型与表达式 第十一组 C++语言程序设计.
Presentation transcript:

第9章 C++的文件操作 “文件”,一般是指内存以外的存储介质上一批数据的集合。C++在语言层次上提供了文件操作的一系列函数用于完成文件的操作,打开、关闭文件,读取、写入文件数据等操作。 1。字符文件与二进制文件 字符文件:又称ASCII文件或文本TEXT文件,它是以一个字节存放一个ASCII码,代表一个字符。例如,32767需要使用5个字节表示,即: 51 50 55 54 55 (十进制表示的ASCII),而浮点数136.56需要使用6个字节表示,即49 51 54 46 53 54。

二进制文件:是指以数据在内存中存储形式原样输出(存放)到文件上去,例136 二进制文件:是指以数据在内存中存储形式原样输出(存放)到文件上去,例136.56是一个float型实数,它在内存中占有4个字节长度。将该4个字节按其在内存中的原来形式存放到文件中。无论该float型数有多大,都只占用4个字节。 ASCII形式表示 00110011 00111110 00110111 00110110 00110111 整数32767在内存 中的存储形式 3 2 7 6 7 01111111 11111111 01111111 11111111 二进制形式表示

可见用ASCII码形式输出与字符一一对应,一个字节代表一个字符,因而便于对字符进行逐个处理,也便于输出字符,缺点是占存储空间较多。二进制文件节省存储空间,而且输入输出速度快,节省时间。 2。缓冲文件系统和非缓冲文件系统 缓冲文件系统是指:系统自动地在内存区为每一个正在使用的文件开辟一个缓冲区。从内存向磁盘输出数据必须先送到内存中的缓冲区,装满缓冲区后才一起送到磁盘文件中去。如果从磁盘向内存读入数据,则一次从磁盘文件中将一批数据输入到内存缓冲区,然后再从缓冲区逐个地将数据送到程序数据区。 非缓冲文件系统是指:系统不自动开辟确定大小的缓冲区,而由程序员为每个文件设定缓冲区。

输出 输入 输出文件缓冲区 程序数据区 输入文件缓冲区 文件信息区 内存 外设 文件类对象 磁盘

3。文件操作 为了调用磁盘文件,缓冲文件系统为每一个文件开辟了一个“文件信息区”,用来存放与文件操作有关的信息。 在C++中,头文件fstream.h中定义了文件类(型),包括: ifstream: 它支持从输入文件中提取数据的各种操作; ofstream:它支持把数据写入文件中的各种操作; fstream: 支持数据的输入与输出操作。 C++中文件操作的步骤 (1). 定义一个文件类(型)的对象: 方法如下: ifstream infile; ofstream outfile; fstream iofile;

(2). 打开文件:建立文件对象与磁盘文件之间的联系; (3). 对打开文件的操作:可以使用成员函数或“>>”“<<”运算符对文件进行读写操作。 (4). 文件操作完成后,应该用成员函数关闭打开的文件。 文件的打开和关闭 (1)文件的打开 (open) 所谓“打开”,实际上是在程序和操作系统之间建立起联系,通过文件的打开操作为所处理的文件定义一个文件指针,文件指针并不是直接指向所处理的文件本身,而是指向内存中用于存放文件信息的文件信息区,在文件打开后文件信息区就与该文件建立了一对一的联系。然后使用文件类所提供的成员函数(类似于成员变量),将数据写入到对应的文件中去。

打开文件的方法可以有: 定义的文件类的对象(变量)后,使用成员函数打开文件: ifstream infile; ofsream outfile; fstream file; infile.open(“myfile_in.txt”); //打开一个只读文件 outfile.open(“myfile_out.txt”); //打开一个只写文件 file.open(“myfile.txt”, ios::in); //以只读方式打开文件 在定义文件类对象时直接打开文件: ifstream infile(“myfile_in.txt”); ofstream outfile(“myfile_out.txt”); fstream file(“myfile.txt”, ios::in);

(2)文件的打开方式 在头文件ios.h中,定义了文件打开方式的枚举成员: enum open_mode{ in = 0x01, //00000001按读方式打开文件 out = 0x02, //00000010按写方式打开文件 ate = 0x04, //00000100打开文件时将文件指针移到 app = 0x08, //00001000 文件的结尾处 trunc = 0x10, //00010000 打开文件时清除原有内容 nocreate = ox20, //00100000 noreplace = 0x40, //01000000 binary = 0x80 //10000000 以二进制方式打开文件 };

每一种打开方式是以一个二进制位来表示的,所以可以用二进制位或运算“|”将允许的几种方式组合起来使用。 如: ios::out | ios::ate //打开一个输出文件并将指针移到文件尾 ios::in | ios::binary //打开一个二进制文件用于输入 ios::out | ios::trunc //打开一个输出文件并清除原有内容

枚举常量名 含义 ios::in ios::out ios::ate ios::app ios::trunc ios::nocreate 打开文件用于输入(读)操作。如果文件存在,将不被截掉,文件定位指针位于文件首,新的数据可写到文件中任何位置。 ios::out 打开文件用于输出(写)操作。如果文件存在,并且没有设置ios::app, ios::ate,ios::in值,则文件被截掉。 ios::ate 如果文件存在,将不被截掉。文件定位指针位于文件尾,新的数据可写到文件中任何位置。 ios::app 如果文件存在,将不被截掉。文件定位指针位于文件尾,新的数据附加到文件尾(不可重写已存在的文件数据)。 ios::trunc 如果文件已存在,则被截为0;如果指定ios::out,同时没有设置ios::app, ios::ate, ios::in,则该模式是隐含的。 ios::nocreate 如果文件不存在,则打开文件失败(不创建新文件)。 ios::noreplace 如果文件存在,打开时只能设置为ios::ate及ios::app方式。 ios::binary 指定文件以二进制方式打开,而不是缺省说明的文本方式。

ifstream类的成员函数open的原型为: 由文件打开方式的说明可知: ifstream类的成员函数open的原型为: open(const char *, int = ios::in, int = filebuf::openprot); 其缺省的文件打开方式为ios::in; ofstream类的成员函数open的原型为: open(const char *, int = ios::out, int = filebuf::openprot); 其缺省的文件打开方式为ios::out; fstream类的成员函数open的原型为: open(const char *, int, int = filebuf::openprot); 其缺省的文件打开方式必须指定。 (3) 文件的关闭(close) “关闭”就是使文件指针变量不指向该文件,也就是使文件指针变量与文件“脱钩”,此后不能再通过该指针对其相连的文件进行读写操作,除非再次打开。

无论是ifstream、ofstream还是fstream,关闭文件的操作都是: close( ); 如:infile.close( ), outfile.close( ), file.close( ); 关闭文件时, 系统把与该文件相关联的内存缓冲区中的数据写到文件中,收回与该文件相关的文件信息区,把文件名与文件对象之间建立的关联断开。 (4)文件操作的保护 在打开文件后,通常要判断打开是否成功。若打开成功,则文件类对象的值为非零值;若打开不成功,则其值为0。为此,打开文件的格式可以写为: ifstream f1(“file.dat”); if(!f1) { cout<<“不能打开文件:”<<“file.dat”<<‘\n’; exit(1); }

char filename[256]; cout<<“输入文件名”; cin>>filename; ofstream f5; f5.open(filename); if(!f5) { cout<<“不能打开文件:”<<“file.dat”<<‘\n’; exit(1); } (5)C++的文本文件操作 C++的三个文件类ifstream、ofstream和fstream由于继承了cin和cout的特性,因此具有与cin和cout相同的成员函数,如与cin.get(char);对应的有:infile.get(char); cin.getline(char *, int size);对应的: infile.getline(char *, int size); cout.put(char); 对应的:outfile.put(char); 此外还有用于标准输入输出设备的提取“>>”和插入“<<”运算符。

例:编写程序,读取源程序文件并复制到目的文件中去。 #include<fstream.h> #include<stdlib.h> void main(void) { char filename_in[256], filename_out[256]; cout<<“输入源文件名:"; cin>>filename_in; cout<<“输入目的文件名:"; cin>>filename_out; ifstream infile(filename_in); //ifstream infile; if(!infile){ //infile.open(filename_in); cout<<“不能打开输入文件:"<<filename_in<<'\n'; exit(-1); } ofstream outfile(filename_out); if(!outfile){ cout<<"不能打开输出文件:"<<filename_out<<'\n'; exit(-2); infile.unsetf(ios::skipws); //设置为不要跳过文件的空格 char ch; while(infile>>ch) //当到达文件结尾时,infile>>ch的返回值为0,结束循环; outfile<<ch; //否则其返回值不为0,继续循环。 infile.close( ); outfile.close( );

处理文件复制问题的另外两个方案: 方案2:(适用于任何类型的文件) char ch; //成员函数完成从源文件中字符读取, while(infile.get(ch)) //这样将不会自动跳过空格。 outfile.put(ch); //将ch中的字符写到目的文件中。 infile.close( ); outfile.close( ); 方案3:(只适用于文本文件) char buff[300]; while(infile.getline(buff,300)) //从源文件中读取一行字符,不含‘\n’ outfile<<buff<<'\n'; //字符;

(6)C++的二进制文件操作 C++的文件类对象可能通过成员函数read( )和write( )实现对二进制文件的读写操作是的,函数的原型为: read(char *buf, int size); 功能:从文件中读取由size所指定的字节数据到buf所指向的存储单元中。 write(char *buf, int size); 功能:将由buf所指向的存储单元中的size个字节数据写入到文件中。

例:产生一个二进制文件,将1~500之间的所有偶数写入文件data.dat中。 #include<fstream.h> #include<stdlib.h> void main(void) { ofstream outfile("d:\\source\\data.dat",ios::out|ios::binary); if(!outfile){ cout<<"不能打开输出文件:data.dat\n"; exit(-1); } for(int i=2;i<500;i+=2) outfile.write((char *)&i,sizeof(int)); //将整数的地址强制转换成字符型指针 outfile.close( );

例:从上例中产生的数据文件data.dat中读取二进制数据,并在显示器上按每行10个数据 的形式显示。 #include<fstream.h> #include<stdlib.h> void main(void) { ifstream infile("d:\\source\\data.dat",ios::binary); if(!infile){ cout<<"不能打开输入文件:data.dat\n"; exit(-1); } int a[250]; infile.read((char *)a,sizeof(int)*249); for(int i=0;i<249;i++){ cout<<a[i]<<'\t'; if((i+1)%10==0) cout<<'\n'; cout<<'\n'; infile.close( );

处理文件复制问题的另一个方案: 方案4: While(!infile.eof( )){ infile.read(buf, 4096); outfile.write(buf, 4096); } //eof( ):用于测试文件结束,当文件结束时,函数返回非0;否则返回值为0; 该程序可以实现任意文件类型的拷贝,包括文本文件、数据文件甚至可执行文件。

(7)文件的随机访问 在文件信息区中存在一个用于指示当前文件读取位置的指针变量,称为文件定位指针,C++语言不仅允许按文件中信息的先后顺序来进行读写,同时也允许从文件中的任何位置开始进行数据的读写操作,这种读写方式就称为文件的随机访问。C++的istream和ostream类中分别提供了几个支持文件随机访问的成员函数。分别是: istream (输入文件)类: seekg(long streampos); 将文件定位指针移动到strampos所指定的位置。 seekg(long streamoff, seek_dir); 将文件定位指针按seek_dir确定的方向移动streamoff位置; tellg( ); 返回输入文件中,文件定位指针当前的位置。

ostream (输出文件)类: seekp(long streampos); 将文件定位指针移动到strampos所指定的位置。 seekp(long streamoff, seek_dir); 将文件定位指针按seek_dir确定的方向移动streamoff位置; tellp( ); 返回输出文件中,文件定位指针当前的位置。 Seek_dir 枚举常量值 功能 ios::beg 文件开头 ios::cur 1 文件指针的当前位置 ios::end 2 文件尾

例如: infile.seekg(500); //文件定位指针移到距文件头500个字节处 infile.seekg(-100,ios::cur); //文件定位指针从当前位置前移100个字节 infile.seekg(100,ios::cur); //文件定位指针从当前位置后移100个字节 outfile.seekp(-100,ios::end); //文件定位指针从文件尾开始前移100个字节 注: 1. 前移:指文件定位指针从文件尾向文件头方向移动(streamoff为负值); 后移:指文件定位指针从文件头向文件尾方向移动; 2. 在移动文件指针时,必须保证移动后的指针值大于0且小于等于文件尾字节编号,否则将导致接着的输入输出操作失败。

例:产生一个5~1000之间的奇数文件(二进制文件),将文件中的第20~30之间的数读出后输出。 #include<fstream.h> #include<iostream.h> void main(void) { ofstream outfile(“data.dat”,ios::out|ios::binary); int i; for(i=5;i<1000;i+=2) outfile.write((char *)&i, sizeof(int)); outfile.close( ); ifstream infile(“data.dat”,ios::in|ios::binary); int x; infile.seekg(20*sizeof(int)); for(i=0;i<10;i++) { infile.read((char *)&x,sizeof(int)); cout<<x<<‘\t’; } infile.close( );

例:设在A盘上已经存在一个二进制格式的文件,其中存放了由1开始的公差为2的一批数,下面的程序判断这批数的最后一个是否是99,如果不是的话,则在文件中已有的数的基础上以相同的规律将数补充到99为止。 #include<iostream.h> #include<fstream.h> #include<stdlib.h> void main(void) { int num, i; fstream fp; fp.open("a:\\data1.txt",ios::in|ios::out|ios::binary); if(!fp) { cout<<"file can't open!"; exit(-1); } fp.seekg(-(long)sizeof(int),ios::end); fp.read((char *)&num,(long)sizeof(int)); for(i=num+2;i<=99;i+=2) fp.write((char *)&i,(long)sizeof(int)); fp.close( );

【例9.9】文本式数据文件的创建与读取数据。典型的C++数据存入文件和由文件获得数据的方法是把对象存入文件和由文件重构对象。本例对提取和插入运算符进行了重载,只用一个“>>”完成重构对象,而只用一个“<<”完成对象存入文件。 class inventory{ string Description; string No; int Quantity; double Cost; double Retail; public: inventory(string="#",string="0",int=0,double=0,double=0); friend ostream&operator<<(ostream&dist,inventory&iv); friend istream&operator>>(istream&sour,inventory&iv); }; //流类作为形式参数必须是引用

inventory::inventory(string des,string no,int quan, double cost,double ret){ Description=des; No=no; Quantity=quan; Cost=cost; Retail=ret;} ostream &operator<<(ostream&dist,inventory&iv){ dist<<left<<setw(20)<<iv.Description<<setw(10)<<iv.No; dist<<right<<setw(10)<<iv.Quantity<<setw(10)<<iv.Cost <<setw(10)<<iv.Retail<<endl; return dist; } //写入文件是自动把数转为数字串后写入 istream&operator>>(istream&sour,inventory&iv){ sour>>iv.Description>>iv.No>>iv.Quantity >>iv.Cost>>iv.Retail; return sour; } //从文件读出是自动把数字串转为数读出,函数体内>>功能不变

int main( ){ inventory car1("夏利2000","805637928",156,80000,105000),car2; inventory motor1("金城125","93612575",302,10000,13000),motor2; ofstream distfile("d:\\Ex9_9.data"); distfile<<car1<<motor1; //注意ofstream是ostream的派生类 distfile.close(); cout<<car1; cout<<motor1; cout<<car2; cout<<motor2; ifstream sourfile("d:\\Ex9_9.data"); //这样分两次打开,可避免读文件时,误改了源文件 sourfile>>car2>>motor2; sourfile.close(); return 0; }