当前位置:高等教育资讯网  >  中国高校课件下载中心  >  大学文库  >  浏览文档

《面向对象程序设计》第八章 C++系统流库的I/O操纵算子(8.1)创建文件流

资源类别:文库,文档格式:DOC,文档页数:5,文件大小:64.5KB,团购合买
dec、hex、oct、 setbase(intn)(设置基数)ws(提出空白字符)、ends(插入一个nul字 符)、endl(插入一个新行并刷新流)、 flush(刷新流)、 resetiosflags(long)等等 ios类的错误性质通常由下列标志指示 goodbit 没有位置位,状态为正常状态
点击下载完整版文档(DOC)

C++系统流库的IO操纵算子 dec、hex、oct、 setbase(intn)(设置基数)、ws(提出空白字符)、ends(插入一个nul字 符)、end(插入一个新行并刷新流)、fush(刷新流)、 resetiosflags(long)等等 ios类的错误性质通常由下列标志指示: goodbit 没有位置位,状态为正常状态 corbit 到达文件末尾 failbit O操作失败 badbit 式图进行非法操作 hardtail 致命性错误 有几个函数可用来检查一个流对象的当前状态,它们都是ios类的成员函数: int restate.返回当前的流状态字 I int eof: 如果提取操作已到达文件尾,则返回非零值 int fail 若 failbit位置位,返回非零值 int bado 若 badbit位置位,返回非零值 若状态字没有位置位,返回非零值 8.1创建文件流 操作系统中另一个常配置的设备是文件设备(磁盘、磁带等),在文件设备上可建立一 个文件,对文件进行IO操作,在对文件处理完后还应关闭文件。 C++系统通过对流类进一步扩展,提供了支持文件IO的能力,这使得程序员在建立和 使用文件时,就象使用cin和cout一样方便。图8-1表示扩展后处理文件I/O的类等级 新派生的五个类用于文件处理 streambuf Istream ostream fstreambase flebuf iostream iStream ofstream fstream 图8-1文件I/流类等级 Filebuf类是 streambuf的派生类,它提供了对文件缓冲区管理的能力,我们一般不涉及 这个类。 Fstreambase类提供了文件处理所需要的全部成员函数,在它的派生类中没有提供 新的成员函数; ifstream类用于文件的输入操作;而 ofstream类用于文件的输出操作; istream 类允许对文件在两个方向上进行操作,这几个类也同时继承了前面介绍的流类的基本类等级

C++系统流库的 I/O 操纵算子 dec 、hex、oct、setbase(int n)(设置基数)、ws(提出空白字符)、ends(插入一个 nul 字 符)、endl(插入一个新行并刷新流)、flush(刷新流)、resetiosflags(long)等等。 ios 类的错误性质通常由下列标志指示: goodbit 没有位置位,状态为正常状态 eofbit 到达文件末尾 failbit I/O 操作失败 badbit 试图进行非法操作 hardfail 致命性错误 有几个函数可用来检查一个流对象的当前状态,它们都是 ios 类的成员函数: int rdstate(); 返回当前的流状态字 int eof(); 如果提取操作已到达文件尾,则返回非零值 int fail(); 若 failbit 位置位,返回非零值 int bad(); 若 badbit 位置位,返回非零值 int good(); 若状态字没有位置位,返回非零值 8.1 创建文件流 操作系统中另一个常配置的设备是文件设备(磁盘、磁带等),在文件设备上可建立一 个文件,对文件进行 I/O 操作,在对文件处理完后还应关闭文件。 C++系统通过对流类进一步扩展,提供了支持文件 I/O 的能力,这使得程序员在建立和 使用文件时,就象使用 cin 和 cout 一样方便。图 8—1 表示扩展后处理文件 I/O 的类等级, 新派生的五个类用于文件处理。 Filebuf 类是 streambuf 的派生类,它提供了对文件缓冲区管理的能力,我们一般不涉及 这个类。Fstreambase 类提供了文件处理所需要的全部成员函数,在它的派生类中没有提供 新的成员函数;ifstream 类用于文件的输入操作;而 ofstream 类用于文件的输出操作;fstream 类允许对文件在两个方向上进行操作,这几个类也同时继承了前面介绍的流类的基本类等级

中定义的成员函数 在使用这些类时,必须在程序中嵌入文件 fstream. h 8.1.1文件的打开和关闭 通过打开一个文件,可以将一个流与一个文件相联结。一个文件在打开时,必须指定文 件打开方式。在ios类中定义的一组枚举常量名给出了可允许的文件打开方式,如表8 所示。 表8-1文件的打开方式 常量名 打开一个文件进行读操作 打开一个文件进行写操作 文件打开时将文件指针定位于文件末尾 添加,向文件输出的内容都添加到文件尾部 trunc 如果文件已经存在,将其长度截断为0,并清除原有内容 socrate如果文件不存在,则打开操作失败 homeplace如果文件存在,除非设置ios:ate或os:ap,否则打开失败 binary 指定文件以二进制方式打开,缺省时为文本方式 除ios:app方式之外,文件刚打开时,指示当前读写位置的文件指针定位于文件的开始 位置,而ios:app使文件当前的写指针定位于文件尾 在打开一个文件时,若指定方式ios:out,而未指定ios:ate或ios:app,则隐含方式为 可以将几种方式通过“或”操作结合起来,例如,打开一个供读和写的文件,其方式可 定义为ios: in/ios:out. 文本文件和二进制文件最根本的区别在于进行LO操作时对“n'’字符的解释方式。在 C++中,这个字符表示的ASCI码是0X0A的字符(换行)。当文件以文本方式打开时,流 类在向文件缓冲区中插入字符时,凡遇到代码为0X0A的字符,都将其扩展为两个字符,即 0X0D和0X0A。反之,当从流中提取一个字符时,当流类遇到字符0X0D时,流类都将它 和其后的字符0X0A合并为一个字符“hn’。当文件以二进制方式打开时,所有的字符都按 一个二进制字节处理,不再对0X0A字符作变换处理 可以有两种方法以一定方式打开一个文件,一种方式是在建立对象时使用构造函数将 个文件和这个流对象联结起来。在 ifstream类、 ofstream类和 istream类中各定义有一个构造 函数,它们是 ifstream am(char int=ios: in, int=filebuf: openport) ofstream: ofstream(char int=ios: out, int -filebuf: openport) fstream fstream( char int, int-filebuf openport 在这三个构造函数中,第一个参数表示要联结的文件名,第二个参数指定文件打开的方 式, ifstream类和 ofstream类的构造函数提供了缺省值。最后一个参数指定文件的保护方式, 这个值和具体的操作系统有关,我们一般只使用缺省指定的 filebuf: penpont值,它是在 filebuf类中定义的一个公有的静态数据成员。 例81:将一个文件的内容拷贝到另一个文件EX81.CPP。 这个程序在遇到文件结束标志时终止。当流对象 Input和 output的生命期结束时,它们

中定义的成员函数。 在使用这些类时,必须在程序中嵌入文件 fstream.h。 8.1.1 文件的打开和关闭 通过打开一个文件,可以将一个流与一个文件相联结。一个文件在打开时,必须指定文 件打开方式。在 ios 类中定义的一组枚举常量名给出了可允许的文件打开方式,如表 8—1 所示。 表 8—1 文件的打开方式 常量名 含义 in 打开一个文件进行读操作 out 打开一个文件进行写操作 ate 文件打开时将文件指针定位于文件末尾 app 添加,向文件输出的内容都添加到文件尾部 trunc 如果文件已经存在,将其长度截断为 0,并清除原有内容 nocreate 如果文件不存在,则打开操作失败 noreplace 如果文件存在,除非设置 ios::ate 或 ios::app,否则打开失败 binary 指定文件以二进制方式打开,缺省时为文本方式 除 ios::app 方式之外,文件刚打开时,指示当前读写位置的文件指针定位于文件的开始 位置,而 ios::app 使文件当前的写指针定位于文件尾。 在打开一个文件时,若指定方式 ios::out,而未指定 ios::ate 或 ios::app,则隐含方式为 ios::trunc。 可以将几种方式通过“或”操作结合起来,例如,打开一个供读和写的文件,其方式可 定义为 ios::in|ios::out. 文本文件和二进制文件最根本的区别在于进行 I/O 操作时对‘\n’字符的解释方式。在 C++中,这个字符表示的 ASCII 码是 0X0A 的字符(换行)。当文件以文本方式打开时,流 类在向文件缓冲区中插入字符时,凡遇到代码为 0X0A 的字符,都将其扩展为两个字符,即 0X0D 和 0X0A。反之,当从流中提取一个字符时,当流类遇到字符 0X0D 时,流类都将它 和其后的字符 0X0A 合并为一个字符‘\n’。当文件以二进制方式打开时,所有的字符都按 一个二进制字节处理,不再对 0X0A 字符作变换处理。 可以有两种方法以一定方式打开一个文件,一种方式是在建立对象时使用构造函数将一 个文件和这个流对象联结起来。在 ifstream 类、ofstream 类和 fstream 类中各定义有一个构造 函数,它们是: ifstream::ifstream(char *,int=ios::in,int =filebuf::openport); ofstream::ofstream(char *,int=ios::out,int =filebuf::openport); fstream::fstream(char *,int,int =filebuf::openport); 在这三个构造函数中,第一个参数表示要联结的文件名,第二个参数指定文件打开的方 式,ifstream 类和 ofstream 类的构造函数提供了缺省值。最后一个参数指定文件的保护方式, 这个值和具体的操作系统有关,我们一般只使用缺省指定的 filebuf::openport 值,它是在 filebuf 类中定义的一个公有的静态数据成员。 例 8_1:将一个文件的内容拷贝到另一个文件 EX8_1.CPP。 这个程序在遇到文件结束标志时终止。当流对象 input 和 output 的生命期结束时,它们

的析构函数分别关闭和这两个对象相联系的文件。可以使用从 fstreambase类继承的成员函 数 eam. clo 来关闭文件流。例如,可以在EX8_1.CPP程序中的 while语句之后增加下面两条语句: 当使用成员函数 closel关闭一个文件流之后,反映流状态的状态字被清零,并且使一个 流对象和文件相脱离 可以使用成员函数open()将一个流对象和一个文件相联结,成员函数open在 fstreambase类中定义,在它的派生类中被重定义为: yoid ifstream: open(char * int=ios. in, int-filebuf openport); void ofstream open(char*, int=ios out, int-filebuf openport) void fstream: open(char * int, int-filebuf: openport); 成员函数open的参数及其意义和前面介绍的相应类的构造函数的参数完全相同 有时,在建立一个流对象时,并不知道这个流对象和那个文件相联系,这时可以使用 ifstream类、 ofstream类和 istream类定义的缺省构造函数建立一个流对象,当以后需要将这 个流对象和一个文件相联系时,可以再使用函数open( 例82:从一个整数组成的文件中读入一个整数,然后将其扩大一倍之后,存入另一个 文件(EX82.CPP)。 8.1.2在流内随机移z stream类中提供了三个成员函数,用于在输入流内随机移动文件的当前指针,它们的 原型是: istream& istream: seekg( streampos); //character g stand for get istream& istream: seekg(streamoff, seek dir) istream& istream:tel!,返回当前文件指针的位置。 其中 streampos和 stream在 iostream. h中使用 typedef定义为: typedef long streampos typedef long streamoff seekin是一个枚举类型,它在ios类中定义为: enum seek dir( beg=0; cur=l; end=2 下面解释成员函数 stream& istream seekg( streamoff, seek dir) 其中, seek dir规定了在输入流中移动文件指针时节参照位置, streamof指定了相对于该参 照位置的偏移量。 Seek dir的值具有的意义如表8-2所示 表 seek dir值的意义 ur 泪对于文件指针的当前位置 泪对于文件的开始位置 相对于文件的结束位置 例如: input seekg(-l0,ios:cur) ntput seekg(-10, ios: end)

的析构函数分别关闭和这两个对象相联系的文件。可以使用从 fstreambase 类继承的成员函 数: void fstream::close(); 来关闭文件流。例如,可以在 EX8_1.CPP 程序中的 while 语句之后增加下面两条语句: input.close(); output.close(); 当使用成员函数 close()关闭一个文件流之后,反映流状态的状态字被清零,并且使一个 流对象和文件相脱离。 可以使用成员函数 open()将一个流对象和一个文件相联结,成员函数 open 在 fstreambase 类中定义,在它的派生类中被重定义为: void ifstream::open(char *,int=ios::in,int =filebuf::openport); void ofstream::open(char *,int=ios::out,int =filebuf::openport); void fstream::open(char *,int ,int =filebuf::openport); 成员函数 open 的参数及其意义和前面介绍的相应类的构造函数的参数完全相同。 有时,在建立一个流对象时,并不知道这个流对象和那个文件相联系,这时可以使用 ifstream 类、ofstream 类和 fstream 类定义的缺省构造函数建立一个流对象,当以后需要将这 个流对象和一个文件相联系时,可以再使用函数 open()。 例 8_2:从一个整数组成的文件中读入一个整数,然后将其扩大一倍之后,存入另一个 文件(EX8_2.CPP)。 8.1.2 在流内随机移动 istream 类中提供了三个成员函数,用于在输入流内随机移动文件的当前指针,它们的 原型是: istream& istream::seekg(streampos);//character g stand for get istream& istream::seekg(streamoff,seek_dir); istream& istream::tellg();//返回当前文件指针的位置。 其中 streampos 和 streamoff 在 iostream.h 中使用 typedef 定义为: typedef long streampos; typedef long streamoff; seekdir 是一个枚举类型,它在 ios 类中定义为: enum seek_dir{beg=0;cur=1;end=2}; 下面解释成员函数: istream& istream::seekg(streamoff,seek_dir); 其中,seek_dir 规定了在输入流中移动文件指针时节参照位置,streamof 指定了相对于该参 照位置的偏移量。Seek_dir 的值具有的意义如表 8—2 所示。 表 8—2 seek_dir 值的意义 符号 含义 cur 相对于文件指针的当前位置 beg 相对于文件的开始位置 end 相对于文件的结束位置 例如:input.seekg(-10,ios::cur) intput seekg(-10,ios::end)

注意:不能将文件指针移到文件开始之前,也不能将文件指针移到文件结束标志之后 Istream类使用teO和 seeker所管理的文件指针称为读指针 ostream类也定义三个成员函数用来管理写指针,它们的原型是: ostream& ostream: seekp(streampos); //character p stand for put ostream& ostream: seekp(streamoff, seek dir) ostream& ostream:tloO,返回当前文件指针的位置 这三个成员函数的含义和对应的 Istream类中的成员函数的含义类似 例83:文件的随机访问EX81.CPP 注意:1、当进行文件随机访问时,文件的打开方式最好指定为二进制方式,以防止将 值为0X0A的字符转换成0XOD和0X0A两个字符,影响程序对文件的正确定位。 2、对于键盘、显示终端以及磁带这样的设备是不能进行随机访问的。 8.1.3将输出流系到输入流上 仍可以使用ios类中定义的成员函数tie将一个输出流系到一个输入流上,例如: fstream in( infile” ofstream out("outfile") in tie( &out) 在以后从输入流i提取数据之前,系统首先自动刷新输出流out的缓冲区。程序员也 可以使用 ostream类中定义的成员函数 flush来刷新一个流的缓冲区,如: out. flush(;或使 用操纵算子fush,如:out<<nush 8.1.4指向流的指针 下面这个程序是EX81.CPP的修订版,它在用户只在命令行给出一个参数的情况下, 将这个命令行参数所指定的文件的内容拷贝到屏幕上。 例84:EX84.CPP。 由于在ios类中将赋值和初始化语句说明为私有的,这就使得两个流对象之间不能进行 赋值和初始化操作,因而流对象不能用作函数的参数或返回值。但可将一个流对象的指针或 引用作为函数的参数或返回类型是可以的,而且也应该这样使用 从 Istream类、 ostream类和 Iostream类中公有派生了三个类: class istream withassign public istream class ostream withassign: public ostream class iostream withassign: public iostream 在这三个派生的类中分别定义了赋值操作 istream withassign& istream withassign: operator=(istream&) ostream withassign& ostream withassign: operator=(ostream&) iostream withassign& iostream withassign: operator=(iostream&); cin被定义为 istream withassign类的对象, cout\cerr和clog都是 ostrem withassign类的 对象,所以这四个预定义的流可以用于赋值操作

注意:不能将文件指针移到文件开始之前,也不能将文件指针移到文件结束标志之后。 Istream 类使用 tellg()和 seekg()所管理的文件指针称为读指针。 ostream 类也定义三个成员函数用来管理写指针,它们的原型是: ostream& ostream::seekp(streampos);//character p stand for put ostream& ostream::seekp(streamoff,seek_dir); ostream& ostream::tellp();//返回当前文件指针的位置。 这三个成员函数的含义和对应的 istream 类中的成员函数的含义类似。 例 8_3:文件的随机访问 EX8_1.CPP。 注意:1、当进行文件随机访问时,文件的打开方式最好指定为二进制方式,以防止将 值为 0X0A 的字符转换成 0X0D 和 0X0A 两个字符,影响程序对文件的正确定位。 2、对于键盘、显示终端以及磁带这样的设备是不能进行随机访问的。 8.1.3 将输出流系到输入流上 仍可以使用 ios 类中定义的成员函数 tie 将一个输出流系到一个输入流上,例如: ifstream in(“infile”); ofstream out(“outfile”); in.tie(&out); 在以后从输入流 in 提取数据之前,系统首先自动刷新输出流 out 的缓冲区。程序员也 可以使用 ostream 类中定义的成员函数 flush()来刷新一个流的缓冲区,如:out.flush();或使 用操纵算子 flush,如:out<<flush; 8.1.4 指向流的指针 下面这个程序是 EX8_1.CPP 的修订版,它在用户只在命令行给出一个参数的情况下, 将这个命令行参数所指定的文件的内容拷贝到屏幕上。 例 8_4:EX8_4.CPP。 由于在 ios 类中将赋值和初始化语句说明为私有的,这就使得两个流对象之间不能进行 赋值和初始化操作,因而流对象不能用作函数的参数或返回值。但可将一个流对象的指针或 引用作为函数的参数或返回类型是可以的,而且也应该这样使用。 从 istream 类、ostream 类和 iostream 类中公有派生了三个类: class istream_withassign:public istream class ostream_withassign:public ostream class iostream_withassign:public iostream 在这三个派生的类中分别定义了赋值操作 istream_withassign& istream_withassign::operator=(istream&); ostream_withassign& ostream_withassign: :operator=(ostream&); iostream_withassign& iostream_withassign: :operator=(iostream&); cin 被定义为 istream_withassign 类的对象,cout\cerr 和 clog 都是 ostrem_withassign 类的 对象,所以这四个预定义的流可以用于赋值操作

8.1.5流类的派生用法 本节将说明建立流类的派生类,以扩充流类适应于具体的应用环境。这个程序通过重载 下标运算符建立一个虚拟文件数组,使在程序中对文件的使用就旬对内存中的数组的使用 样 考虑一个int类型的数组 int array 101 当我们引用数组中的一个元素aa时,C++编译器按表达式*(aray+i)来引用这个元素, 数组名aray作为基准地址。如果将这个数组实现为一个文件,则基准地址就是文件的开始 位置。 使用下标运算符引用的一个数组元素既可以用作左值,又可以用作右值,因此,当重载 下标运算符操作文件时,必须注意对这种情况的处理。设建立的文件数组的类名为 filearray, 从下面的程序片段 int I: a[l]=100 F=a[1; 可以重载赋值运算符,用于将一个数据作为数组的元素写入到文件中,而当从文件数组读入 个元素时,我们就不能重载赋值运算符,但在将a[置给一个变量i时,它的类型发生了 变化,因此我们可以定义一个类型转换函数,用于从文件数组中读一个元素。下面给出相应 的程序。 例85:EX85.CPP

8.1.5 流类的派生用法 本节将说明建立流类的派生类,以扩充流类适应于具体的应用环境。这个程序通过重载 下标运算符建立一个虚拟文件数组,使在程序中对文件的使用就旬对内存中的数组的使用一 样。 考虑一个 int 类型的数组 int array[10]; 当我们引用数组中的一个元素 array[i]时,C++编译器按表达式*(array+i)来引用这个元素, 数组名 array 作为基准地址。如果将这个数组实现为一个文件,则基准地址就是文件的开始 位置。 使用下标运算符引用的一个数组元素既可以用作左值,又可以用作右值,因此,当重载 下标运算符操作文件时,必须注意对这种情况的处理。设建立的文件数组的类名为 filearray, 从下面的程序片段: int I; filearray a; a[1]=100; i=a[1]; 可以重载赋值运算符,用于将一个数据作为数组的元素写入到文件中,而当从文件数组读入 一个元素时,我们就不能重载赋值运算符,但在将 a[1]置给一个变量 i 时,它的类型发生了 变化,因此我们可以定义一个类型转换函数,用于从文件数组中读一个元素。下面给出相应 的程序。 例 8_5:EX8_5.CPP

点击下载完整版文档(DOC)VIP每日下载上限内不扣除下载券和下载次数;
按次数下载不扣除下载券;
24小时内重复下载只扣除一次;
顺序:VIP每日次数-->可用次数-->下载券;
已到末页,全文结束
相关文档

关于我们|帮助中心|下载说明|相关软件|意见反馈|联系我们

Copyright © 2008-现在 cucdc.com 高等教育资讯网 版权所有