第7章 输入/输出流 文件和I/O流概述 标准I/O流的对象及其成员函数 文件流
7.1 基本概念(1/4) 文件可以保存程序运行的结果 文件使程序操作大量数据成为可能 大型系统的运行需要文件支持
7.1 基本概念(2/4) 文件是一组相关联的数据的集合 C++将文件看成有序的字节流 文件被打开后,操作系统为该文件建立的一个缓冲区,或称为一个字节序列,即流
7.1 基本概念(3/4) 文件 C++采用相同的方式操作普通文件和I/O设备 普通文件 二进制文件 文本文件 输入输出设备:键盘、显示器、打印机等 标准输入流(用指针stdin操作) 标准输出流(用指针stdout操作) 标准错误流(用指针stderr操作) C++采用相同的方式操作普通文件和I/O设备
7.1 基本概念(4/4) 文件的操作 格式化输入输出(文本) 块输入输出(二进制)
7.2 I/O流概述 程序中,对数据的输入/输出是以字节流实现的 应用程序对字节序列作出各种数据解释 流类对象可以建立和删除,可以从流中获取数据和向流添加数据
流类库 流库(stream library)是用继承方法建立的输入输出类库 流库具有两个平行的基类:streambuf 和 ios 类,所有流类均以两者 之一作为基类 streambuf 类提供对缓冲区的低级操作 设置缓冲区 对缓冲区指针操作 向缓冲区存/取字符 ios 类及其派生类提供用户使用流类的接口,支持对streambuf 的缓 冲区输入/输出的格式化或非格式化转换
流类库 1. streambuf 对缓冲区的低级操作 streambuf filebuf strstreambuf stdiobuf
流类库 1. streambuf 对缓冲区的低级操作 文件缓冲区管理 streambuf filebuf strstreambuf stdiobuf 文件缓冲区管理
流类库 1. streambuf 对缓冲区的低级操作 字符串缓冲区管理 streambuf filebuf strstreambuf stdiobuf 字符串缓冲区管理
流类库 1. streambuf 对缓冲区的低级操作 标准I/O缓冲区管理 streambuf filebuf strstreambuf stdiobuf 标准I/O缓冲区管理
流类库 2. ios 提供用户接口 ios istream ostream istream_withassign ifstream istrstream ostream_withassign ofstream ostrstream iostream fstream strstream stdiostream
流类库 2. ios 提供用户接口 ios 输入流 istream ostream 输出流 istream_withassign ifstream istrstream ostream_withassign ofstream ostrstream iostream fstream strstream stdiostream
流类库 2. ios 提供用户接口 ios 输入流 输出流 ifstream istrstream ofstream ostrstream istream ostream 输出流 istream_withassign ifstream istrstream ostream_withassign ofstream ostrstream 输入文件流 输入串流 输出文件流 输出串流 iostream fstream strstream stdiostream
流类库 2. ios 提供用户接口 ios 输入流 输出流 输入文件流 输入串流 输出文件流 输出串流 iostream 输入/输出流 istream ostream 输出流 istream_withassign ifstream istrstream ostream_withassign ofstream ostrstream 输入文件流 输入串流 输出文件流 输出串流 iostream 输入/输出流 fstream strstream stdiostream
流类库 2. ios 提供用户接口 ios 输入流 输出流 输入文件流 输入串流 输出文件流 输出串流 输入/输出流 fstream istream ostream 输出流 istream_withassign ifstream istrstream ostream_withassign ofstream ostrstream 输入文件流 输入串流 输出文件流 输出串流 iostream 输入/输出流 fstream strstream stdiostream 输入/输出文件流 输入/输出串流 标准输入/输出流
流类库 2. ios 提供用户接口 ios 输入流 输出流 istream_withassign ostream_withassign ifstream istrstream ostream_withassign ofstream ostrstream 输入文件流 重载运算符“=” 输入串流 输出文件流 重载运算符“=” 输出串流 iostream 输入/输出流 fstream strstream stdiostream 输入/输出文件流 输入/输出串流 标准输入/输出流
流类库 2. ios 提供用户接口 ios 输入流 输出流 输入文件流 输入串流 输出文件流 输出串流 输入/输出流 istream ostream 输出流 istream_withassign ifstream istrstream ostream_withassign ofstream ostrstream 输入文件流 重载运算符“=” 输入串流 输出文件流 重载运算符“=” 输出串流 iostream 输入/输出流 fstream strstream stdiostream 输入/输出文件流 输入/输出串流 标准输入/输出流
7.3 头文件 iostream.h 包含操作所有输入/输出流所需的基本信息 含有cin、cout、cerr、clog对象,提供无格式和格式化的I/O iomanip.h 包含格式化I/O操纵算子,用于指定数据输入输出的格式 fstream.h 处理文件信息,包括建立文件,读/写文件的各种操作接口 每一种C++版本通常还包含其他一些与I/O相关的库,提供特定系统的某些功能
7.4 标准I/O流的对象及其成员函数 标准流是C++预定义的对象,提供内存外部设备进行数据交互功能 流的操作是流类的公有成员函数
标准流对象 (1) cin istream 类的对象,通常连向键盘,可以重定向 (2) cout ostream 类的对象,通常连向显示器,可以重定向 (3) cerr ostream 类的对象,连向显示器。不能重定向 (4) clog ostream 类的对象,连向打印机。不能重定向
#include<iostream.h> void fn ( int a , int b ) { if ( b == 0 ) 7.2.1 标准流 // 例7-1 重定向的演示 #include<iostream.h> void fn ( int a , int b ) { if ( b == 0 ) cerr << "Zero encountered. The message connot be redirected.\n" ; else cout << a / b << endl ; } void main ( ) { fn ( 20 , 2 ) ; fn ( 20 , 0 ) ;
#include<iostream.h> void fn ( int a , int b ) { if ( b == 0 ) 7.2.1 标准流 // 例7-1 重定向的演示 #include<iostream.h> void fn ( int a , int b ) { if ( b == 0 ) cerr << "Zero encountered. The message connot be redirected.\n" ; else cout << a / b << endl ; } void main ( ) { fn ( 20 , 2 ) ; fn ( 20 , 0 ) ; 不能重定向 可以重定向 cout 重定向方法 把程序编译成 .exe文件 在 DOS 状态下 以命令参数形式对标准流重定向
7.5 文件处理 各种计算机应用系统通常把一些相关信息组织起来保存在外存储器中, 称为文件,并用一个名字(称为文件名)加以标识 7.5 文件处理 各种计算机应用系统通常把一些相关信息组织起来保存在外存储器中, 称为文件,并用一个名字(称为文件名)加以标识 C++把文件看成无结构的字节流, 编码方式: 文本文件 二进制文件 存取方式: 顺序文件 随机文件 ifstream、ofstream 和 fstream 类用于内存与文件之间的数据传输
7.5.1 文件和流 7.5.1 文件和流 0 1 2 3 4 5 n-1 文件长度 = n 文件字节序号 文件结束符
7.5.1 文件和流 7.5.1 文件和流 0 1 2 3 4 5 n-1 文件指针
7.5.1 文件和流 7.5.1 文件和流 0 1 2 3 4 5 n-1 文件结束
7.5.1 文件和流 读文件 读/写文件 写文件 ------------ 内存 0 1 2 3 4 5 n-1 ifstream fin 7.5.1 文件和流 7.5.1 文件和流 0 1 2 3 4 5 n-1 读文件 读/写文件 写文件 ifstream fin fstream finout ofstream fout ------------ 内存
7.5.2 打开和关闭文件 7.5.2 打开和关闭文件 文件操作的基本步骤: 打开文件 读 / 写文件 关闭文件
1.打开文件 包括建立文件流对象;与外部文件关联;指定文件的打开方式 打开文件有两种方法: 7.5.2 打开和关闭文件 1.打开文件 包括建立文件流对象;与外部文件关联;指定文件的打开方式 打开文件有两种方法: 首先建立流对象,然后调用fstream::open()函数连接外部文件 流类 对象名 ; 对象名 . open ( 文件名 , 方式 ) ; 调用流类带参数的构造函数,建立流对象的同时连接外部文件 流类 对象名 ( 文件名 , 方式 ) ; ifstream、ofstream 或 fstream
void open ( const char * , int mode , int = filebuf :: openprot ) ; 7.5.2 打开和关闭文件 1.打开文件 open 函数原型 void open ( const char * , int mode , int = filebuf :: openprot ) ; filebuf、ifstream、ofstream、fstream的构造函数具有相同的参数和缺省值 文件流的构造函数和 open ( ) 函数用于打开文件,析构函数在流对象被删除 之前关闭文件
void open ( const char * , int mode , int = filebuf :: openprot ) ; 7.5.2 打开和关闭文件 1.打开文件 open 函数原型 void open ( const char * , int mode , int = filebuf :: openprot ) ; filebuf、ifstream、ofstream、fstream的构造函数具有相同的参数和缺省值 文件流的构造函数和 open ( ) 函数用于打开文件,析构函数在流对象被删除 之前关闭文件 其中,第一个参数表示相关联的文件名
void open ( const char * , int mode , int = filebuf :: openprot ) ; 7.5.2 打开和关闭文件 1.打开文件 open 函数原型 void open ( const char * , int mode , int = filebuf :: openprot ) ; filebuf、ifstream、ofstream、fstream的构造函数具有相同的参数和缺省值 文件流的构造函数和 open ( ) 函数用于打开文件,析构函数在流对象被删除 之前关闭文件 其中,第一个参数表示相关联的文件名 第二个参数表示文件的打开方式
void open ( const char * , int mode , int = filebuf :: openprot ) ; 7.5.2 打开和关闭文件 1.打开文件 open 函数原型 mode 参数文件打开方式 标识常量 值 意义 ios::in 0x0001 读方式打开文件 ios::out 0x0002 写方式打开文件 ios::ate 0x0004 打开文件时,指针指向文件尾 ios::app 0x0008 追加方式 ios::trunc 0x0010 删除文件现有内容 ios::nocreate 0x0020 如果文件不存在,则打开操作失败 ios::noreplace 0x0040 如果文件存在,则打开操作失败 ios::binary 0x0080 二进制方式打开,默认为文本方式 void open ( const char * , int mode , int = filebuf :: openprot ) ; filebuf、ifstream、ofstream、fstream的构造函数具有相同的参数和缺省值 文件流的构造函数和 open ( ) 函数用于打开文件,析构函数在流对象被删除 之前关闭文件 其中,第一个参数表示相关联的文件名 第二个参数表示文件的打开方式
void open ( const char * , int mode , int = filebuf :: openprot ) ; 7.5.2 打开和关闭文件 1.打开文件 open 函数原型 void open ( const char * , int mode , int = filebuf :: openprot ) ; filebuf::openprot operating system default filebuf::sh_compat Compatibility share mode (MS-DOS only). filebuf::sh_none Exclusive mode — no sharing. filebuf::sh_read Read sharing allowed. filebuf::sh_write Write sharing allowed. The filebuf::sh_read and filebuf::sh_write modes can be combined with the logical OR ( || ) operator. 文件保护模式参数 filebuf、ifstream、ofstream、fstream的构造函数具有相同的参数和缺省值 文件流的构造函数和 open ( ) 函数用于打开文件,析构函数在流对象被删除 之前关闭文件 其中,第一个参数表示相关联的文件名 第二个参数表示文件的打开方式 第三个参数是文件的保护方式,一般只用缺省值
1.打开文件 用第一种方式打开文件: 打开一个已有文件datafile.dat,准备读: 7.5.2 打开和关闭文件 1.打开文件 用第一种方式打开文件: 打开一个已有文件datafile.dat,准备读: ifstream infile ; // 建立输入文件流对象 infile.open( "datafile.dat" , ios::in ) ; // 连接文件,指定打开方式 打开(创建)一个文件newfile.dat,准备写: ofstream outfile ; // 建立输出文件流对象 outfile.open( "d:\\newfile.dat" , ios::out ) ; // 连接文件,指定打开方式
1.打开文件 第二种方法 调用fstream带参数构造函数 : 例1 7.5.2 打开和关闭文件 1.打开文件 第二种方法 调用fstream带参数构造函数 : 例1 ifstream infile ( "datafile.dat" , ios::in ) ; ofstream outfile ( "d:\\newfile.dat" , ios::out ); fstream rwfile ( "myfile.dat" , ios::in | ios::out ) ; 用或运算符 “|” 连接 两个表示打开方式的标识常量
1.打开文件 第二种方法 调用fstream带参数构造函数 : 例1 例2 打开一个二进制文件进行追加操作 : 7.5.2 打开和关闭文件 1.打开文件 第二种方法 调用fstream带参数构造函数 : 例1 ifstream infile ( "datafile.dat" , ios::in ) ; ofstream outfile ( "d:\\newfile.dat" , ios::out ); fstream rwfile ( "myfile.dat" , ios::in | ios::out ) ; 例2 打开一个二进制文件进行追加操作 : ofstream ofile ( "a:\\binary" , ios :: binary | ios :: app ) ; // 对文件写操作 // …… ofile . close ( ) ;
1.打开文件 打开一个输入文件流 必须说明类型为 ifstream 的对象 打开一个输出文件流 必须说明类型为 ofstream 的对象 7.5.2 打开和关闭文件 1.打开文件 打开一个输入文件流 必须说明类型为 ifstream 的对象 打开一个输出文件流 必须说明类型为 ofstream 的对象 要建立输入和输出的文件流 必须说明类型为 fstream 的对象 例如: ifstream in ; // input ofstream out ; // output fstream both ; // input and output
2.关闭文件 关闭文件操作包括把缓冲区数据完整地写入文件,添加文件结束标志, 切断流对象和外部文件的连接 若流对象的生存期没有结束,可以重用 7.5.2 打开和关闭文件 2.关闭文件 关闭文件操作包括把缓冲区数据完整地写入文件,添加文件结束标志, 切断流对象和外部文件的连接 若流对象的生存期没有结束,可以重用 当一个流对象的生存期结束,系统也会自动关闭文件 例如: ofstream ofile ; // 创建输出文件流 ofile . open ( "myfile1" ) ; // ofile流与文件“myfile1”相关联 …… // 访问文件“myfile1” ofile . close ( ) ; // 关闭文件“myfile1” ofile . open ( "myfile2" ) ; // 重用ofile流
ofstream ofile ( "myfile1" ) ; 7.5.2 打开和关闭文件 2.关闭文件 关闭文件操作包括把缓冲区数据完整地写入文件,添加文件结束标志, 切断流对象和外部文件的连接 若流对象的生存期没有结束,可以重用 当一个流对象的生存期结束,系统也会自动关闭文件 等价于使用构造函数: ofstream ofile ( "myfile1" ) ; 例如: ofstream ofile ; // 创建输出文件流 ofile . open ( "myfile1" ) ; // ofile流与文件“myfile1”相关联 …… // 访问文件“myfile1” ofile . close ( ) ; // 关闭文件“myfile1” ofile . open ( "myfile2" ) ; // 重用ofile流
2.关闭文件 关闭文件操作包括把缓冲区数据完整地写入文件,添加文件结束标志, 切断流对象和外部文件的连接 若流对象的生存期没有结束,可以重用 7.5.2 打开和关闭文件 2.关闭文件 关闭文件操作包括把缓冲区数据完整地写入文件,添加文件结束标志, 切断流对象和外部文件的连接 若流对象的生存期没有结束,可以重用 当一个流对象的生存期结束,系统也会自动关闭文件 clos ( ) 函数关闭文件 但流对象仍然存在 例如: ofstream ofile ; // 创建输出文件流 ofile . open ( "myfile1" ) ; // ofile流与文件“myfile1”相关联 …… // 访问文件“myfile1” ofile . close ( ) ; // 关闭文件“myfile1” ofile . open ( "myfile2" ) ; // 重用ofile流
2.关闭文件 关闭文件操作包括把缓冲区数据完整地写入文件,添加文件结束标志, 切断流对象和外部文件的连接 若流对象的生存期没有结束,可以重用 7.5.2 打开和关闭文件 2.关闭文件 关闭文件操作包括把缓冲区数据完整地写入文件,添加文件结束标志, 切断流对象和外部文件的连接 若流对象的生存期没有结束,可以重用 当一个流对象的生存期结束,系统也会自动关闭文件 例如: ofstream ofile ; // 创建输出文件流 ofile . open ( "myfile1" ) ; // ofile流与文件“myfile1”相关联 …… // 访问文件“myfile1” ofile . close ( ) ; // 关闭文件“myfile1” ofile . open ( "myfile2" ) ; // 重用ofile流 重用流对象
7.5.3 文本文件 文本文件用默认方式打开 文本文件用文本文件流进行读/写操作 文本文件是顺序存取文件 描述一个对象的信息称为一个记录 7.5.3 文本文件 7.5.3 文本文件 文本文件用默认方式打开 文本文件用文本文件流进行读/写操作 文本文件是顺序存取文件 描述一个对象的信息称为一个记录 文本文件本身没有记录逻辑结构 通常一个逻辑记录用换行符分隔;数据项之间可以用空白符、 换行符、制表符等分隔
7.5.3 文本文件 2 4 3 7 8 读文件 int a , b ; fin >> a >> b ; 7.5.3 文本文件 7.5.3 文本文件 0 1 2 3 4 5 …… 2 4 3 7 8 读文件 ifstream fin int a , b ; fin >> a >> b ;
7.5.3 文本文件 2 4 3 7 8 读文件 int a , b ; fin >> a >> b ; 7.5.3 文本文件 7.5.3 文本文件 0 1 2 3 4 5 …… 2 4 3 7 8 读文件 ifstream fin int a , b ; fin >> a >> b ; a 0X00f3
7.5.3 文本文件 2 4 3 7 8 读文件 int a , b ; fin >> a >> b ; 7.5.3 文本文件 7.5.3 文本文件 0 1 2 3 4 5 …… 2 4 3 7 8 读文件 ifstream fin int a , b ; fin >> a >> b ; a 0X00f3 b 0X004e
7.5.3 文本文件 2 4 3 7 8 int a , b ; int c ; fin >> a >> b ; 7.5.3 文本文件 7.5.3 文本文件 0 1 2 3 4 5 …… 2 4 3 7 8 ofstream fout int a , b ; fin >> a >> b ; int c ; c = a * b ; fout << "c= " <<c<<endl ; a 0X00f3 b 0X004e
7.5.3 文本文件 2 4 3 7 8 int a , b ; int c ; fin >> a >> b ; 7.5.3 文本文件 7.5.3 文本文件 0 1 2 3 4 5 …… 2 4 3 7 8 ofstream fout int a , b ; fin >> a >> b ; int c ; c = a * b ; fout << "c= " <<c<<endl ; a 0X00f3 b 0X004e c 0X0141
7.5.3 文本文件 7.5.3 文本文件 0 1 2 3 4 5 …… 2 4 3 7 8 写文件 ofstream fout int a , b ; fin >> a >> b ; int c ; c = a * b ; fout << "c= " <<c<<endl ; a 0X00f3 b 0X004e c 0X0141
7.5.3 文本文件 c = 2 4 3 7 8 写文件 int a , b ; int c ; 7.5.3 文本文件 7.5.3 文本文件 0 1 2 3 4 5 …… c = 2 4 3 7 8 写文件 ofstream fout int a , b ; fin >> a >> b ; int c ; c = a * b ; fout << "c= " <<c<<endl ; a 0X00f3 "c= " b 0X004e c 0X0141
7.5.3 文本文件 c = 2 4 3 7 8 3 2 1 写文件 int a , b ; int c ; 7.5.3 文本文件 7.5.3 文本文件 0 1 2 3 4 5 …… c = 2 4 3 7 8 3 2 1 写文件 ofstream fout int a , b ; fin >> a >> b ; int c ; c = a * b ; fout << "c= " <<c<<endl ; a 0X00f3 b 0X004e c 0X0141
7.5.3 文本文件 7.5.3 文本文件 0 1 2 3 4 5 …… c = 2 4 3 7 8 3 2 1 \n 写文件 ofstream fout int a , b ; fin >> a >> b ; int c ; c = a * b ; fout << "c= " <<c<<endl ; a 0X00f3 b 0X004e c 0X0141 endl
7.5.3 文本文件 7.5.3 文本文件 0 1 2 3 4 5 …… c = 2 4 3 7 8 3 2 1 \n ofstream fout int a , b ; fin >> a >> b ; int c ; c = a * b ; fout << "c= " <<c<<endl ; a 0X00f3 b 0X004e c 0X0141
用FILE结构操作文件 打开方式 描述 r 打开一个供读取数据的文件 w 建立或打开一个供写入数据的文件,如果该文件已经存在,则废弃文件内容 a 建立或打开一个供写入数据的文件,如果文件已经存在,则写入的数据将追加到文件的尾部 r+ 打开一个已存在的文件,该文件可以写入和读出数据 w+ 建立或打开一个可供读和写的文件,如果文件已存在则废弃文件内容 a+ 建立或打开一个可供读和写的文件,如果文件已存在则写入的数据追加到文件的尾部 B 打开一个二进制文件
//例7-2 使用FILE指针新建一个文本文件,写入了字符串"This is a test file. " //文件ex16_1.cpp #include <stdio.h> main() { FILE *fptr; //定义FILE指针 //打开或创建文件 if ((fptr = fopen("test.txt","w")) != NULL) { //往文件中写入字符串 fprintf(fptr, "This is a test file."); fclose(fptr); //关闭文件 } else printf("Open file error.\n"); return 0; 打开、建立文本文件:fopen(文件名,“打开方式w”) 写文本文件:fprint(文件指针,字符串) 关闭文件:fclose(文件指针)
//例7-3 将字符、字符串、整数、浮点数、结构等类型的数据写入文件(1/2) //例7-3 将字符、字符串、整数、浮点数、结构等类型的数据写入文件(1/2) //文件ex16_2.cpp ,写文件 #include <stdio.h> struct Test{ int a; double b; }; main() { Test st; st.a = 10; st.b = 1.1; FILE *fptr; //声明文件指针 //打开文件 if((fptr=fopen("writetest.dat","wb"))!=NULL) {
//例7-3 将字符、字符串、整数、浮点数、结构等类型的数据写入文件(2/2) //例7-3 将字符、字符串、整数、浮点数、结构等类型的数据写入文件(2/2) //以二进制方式写入数据 fwrite(&st, sizeof(st),1,fptr); //以字符方式写入一个字符 fputc('a', fptr); //以字符方式写入一个字符串 fputs("Beijing", fptr); //以字符方式写入整数和浮点数 fprintf(fptr, " %d %f ", 23, 12.34); //关闭文件 fclose(fptr); } else printf("Open file error.\n"); return 0;
//例7-4将7-3创建的文件中的数据读出来(1/2) //文件ex16_4.cpp,读二进制文件 #include <stdio.h> struct Test{ int a; double b; }; main() { Test st; char s[20]; int m; float n; char c; FILE *fptr; if((fptr=fopen("writetest.dat","rb"))!=NULL) {
//例7-4将7-3创建的文件中的数据读出来(2/2) fread(&st,sizeof(st),1,fptr); c = fgetc(fptr); fgets(s,8,fptr); fscanf(fptr," %d %f ",&m,&n); fclose(fptr); printf("STRUCT st: a = %d, b = %f\n", st.a, st.b); printf("CHAR c = '%c'\n", c); printf("STRING s = %s\n", s); printf("INTEGER m = %d, FLOAT n = %f\n", m, n); } else printf("File open error.\n"); return 0;
7.5.4 二进制文件 二进制文件以基本类型数据在内存的二进制表示形式存放 数据,不对写入或读出的数据做格式转换 7.5.4 二进制文件 7.5.4 二进制文件 二进制文件以基本类型数据在内存的二进制表示形式存放 数据,不对写入或读出的数据做格式转换 二进制文件的读写方式由程序控制 打开二进制文件用binary方式 二进制文件是随机存取文件
7.5.4 二进制文件 7.5.4 二进制文件 随机访问流 流的状态表示:流的内容、长度和操作位置 beg end cur
istream 类操作流读指针的成员函数 istream & istream :: seekg ( long pos) ; 7.5.4 二进制文件 istream 类操作流读指针的成员函数 istream & istream :: seekg ( long pos) ; 作用 读指针从流的起始位置向后移动由pos指定字节 istream & istream :: seekg ( long off, ios::seek_dir ) ; 作用 读指针从流的seek_dir位置移动 off 指定字节 ios::seek_dir 值: cur 相对于当前读指针所指定的当前位置 beg 相对于流的开始位置 end 相对于流的结尾处 enum ios::seek_dir { beg = 0 ; cur = 1 , end = 2 } ;
istream 类操作流读指针的成员函数 istream & istream :: seekg ( long pos) ; 7.5.4 二进制文件 istream 类操作流读指针的成员函数 istream & istream :: seekg ( long pos) ; 作用 读指针从流的起始位置向后移动由pos指定字节 istream & istream :: seekg ( long off, ios::seek_dir ) ; 作用 读指针从流的seek_dir位置移动 off 指定字节 istream & istream :: teelg () ; 作用 返回读指针当前所指位置值
input . seekg ( - 10 , ios :: cur ) ; // 读指针以当前位置为基准,向前移动 10 个字节 7.5.4 二进制文件 例1: istream input ; …… input . seekg ( - 10 , ios :: cur ) ; // 读指针以当前位置为基准,向前移动 10 个字节 beg end cur cur
input . seekg ( 10 , ios :: beg ) ; // 读指针从流的开始位置,向后移动 10 个字节 7.5.4 二进制文件 例1: istream input ; …… 函数 seekg ( n ) ; 等价于 seekg ( n , ios::beg ) ; input . seekg ( 10 , ios :: beg ) ; // 读指针从流的开始位置,向后移动 10 个字节 beg end cur cur
input . seekg ( -10 , ios :: end ) ; // 读指针从流的结尾,向前移动 10 个字节 7.5.4 二进制文件 例1: istream input ; …… input . seekg ( -10 , ios :: end ) ; // 读指针从流的结尾,向前移动 10 个字节 beg end cur cur
ostream 类操作流写指针的成员函数 ostream & ostream :: seekp ( long pos ) ; 7.5.4 二进制文件 ostream 类操作流写指针的成员函数 ostream & ostream :: seekp ( long pos ) ; 作用 写指针从流的起始位置向后移动由参数指定字节 ostream & ostream :: seekp ( long off , ios::seek_dir ) ; 作用 写指针从流的seek_dir位置移动由 off 指定字节 ostream & ostream :: teelp ( ) ; 作用 返回写指针当前所指位置值
它们也可以用于文本流,但必须保证流中存储数据是ASCII码, 7.5.4 二进制文件 适于二进制流操作的成员函数 这些函数操作对象是单字节数据 它们也可以用于文本流,但必须保证流中存储数据是ASCII码, 并且不会跳过空白字符
适于二进制流操作的成员函数 istream 类中三个操作字节数据的成员函数 7.5.4 二进制文件 适于二进制流操作的成员函数 istream 类中三个操作字节数据的成员函数 istream & istream :: get ( char & c ) ; 作用 从流中提取一个字节数据,更新对象 c int istream :: get ( ) ; 作用 函数值返回流中一个字节数据 istream & istream :: read ( char * buf , int n ) ; 作用 从流中提取 n 个字节数据,更新对象 buf
ostream 类中两个操作字节数据的成员函数 7.5.4 二进制文件 适于二进制流操作的成员函数 ostream 类中两个操作字节数据的成员函数 ostream & ostream :: put ( char c ) ; 作用:向流插入一个字节数据 ostream & ostream :: write ( char * buf , int n ) ; 作用:向流插入 buf 对象的由第二个参数指定数目的字节数据 例: char * s = "string buffer" ; cout . write ( s , strlen ( s ) ) ; // 插入一串字符 cout . put ( '\n' ) ; // 插入一个新行符
例7-21 随机文件读写 #include <fstream.h> void main () 例7-21 随机文件读写 7.5.4 二进制文件 #include <fstream.h> void main () { fstream f( "a:DATA.dat" , ios::in | ios::out | ios::binary ) ; int i ; for( i = 0; i < 20 ; i ++ ) f.write((char *)&i, sizeof(int) ) ; long pos = f.tellp() ; for( i = 20; i<40 ; i ++ ) f.write( (char*)&i, sizeof(int) ) ; f.seekg(pos) ; f.read((char*)&i, sizeof(int) ) ; cout << "The data stored is " << i << endl ; f.seekp( 0, ios::beg ) ; for( i = 0; i<40 ; i ++ ) { f.read( (char*)&i, sizeof(int) ) ; cout<<i<<ends; } cout<<endl; }
例7-21 随机文件读写 #include <fstream.h> void main () 例7-21 随机文件读写 7.5.4 二进制文件 #include <fstream.h> void main () { fstream f( "a:DATA.dat" , ios::in | ios::out | ios::binary ) ; int i ; for( i = 0; i < 20 ; i ++ ) f.write((char *)&i, sizeof(int) ) ; long pos = f.tellp() ; for( i = 20; i<40 ; i ++ ) f.write( (char*)&i, sizeof(int) ) ; f.seekg(pos) ; f.read((char*)&i, sizeof(int) ) ; cout << "The data stored is " << i << endl ; f.seekp( 0, ios::beg ) ; for( i = 0; i<40 ; i ++ ) { f.read( (char*)&i, sizeof(int) ) ; cout<<i<<ends; } cout<<endl; } // 打开随机文件
例7-21 随机文件读写 #include <fstream.h> 注意类型转换 void main () 例7-21 随机文件读写 7.5.4 二进制文件 #include <fstream.h> void main () { fstream f( "a:DATA.dat" , ios::in | ios::out | ios::binary ) ; int i ; for( i = 0; i < 20 ; i ++ ) f.write((char *)&i, sizeof(int) ) ; long pos = f.tellp() ; for( i = 20; i<40 ; i ++ ) f.write( (char*)&i, sizeof(int) ) ; f.seekg(pos) ; f.read((char*)&i, sizeof(int) ) ; cout << "The data stored is " << i << endl ; f.seekp( 0, ios::beg ) ; for( i = 0; i<40 ; i ++ ) { f.read( (char*)&i, sizeof(int) ) ; cout<<i<<ends; } cout<<endl; } 注意类型转换 // 打开随机文件 // 先写入 20 个整数
例7-21 随机文件读写 #include <fstream.h> void main () 例7-21 随机文件读写 7.5.4 二进制文件 #include <fstream.h> void main () { fstream f( "a:DATA.dat" , ios::in | ios::out | ios::binary ) ; int i ; for( i = 0; i < 20 ; i ++ ) f.write((char *)&i, sizeof(int) ) ; long pos = f.tellp() ; for( i = 20; i<40 ; i ++ ) f.write( (char*)&i, sizeof(int) ) ; f.seekg(pos) ; f.read((char*)&i, sizeof(int) ) ; cout << "The data stored is " << i << endl ; f.seekp( 0, ios::beg ) ; for( i = 0; i<40 ; i ++ ) { f.read( (char*)&i, sizeof(int) ) ; cout<<i<<ends; } cout<<endl; } // 打开随机文件 // 先写入 20 个整数 // 记录当前写指针位置值
例7-21 随机文件读写 #include <fstream.h> void main () 例7-21 随机文件读写 7.5.4 二进制文件 #include <fstream.h> void main () { fstream f( "a:DATA.dat" , ios::in | ios::out | ios::binary ) ; int i ; for( i = 0; i < 20 ; i ++ ) f.write((char *)&i, sizeof(int) ) ; long pos = f.tellp() ; for( i = 20; i<40 ; i ++ ) f.write( (char*)&i, sizeof(int) ) ; f.seekg(pos) ; f.read((char*)&i, sizeof(int) ) ; cout << "The data stored is " << i << endl ; f.seekp( 0, ios::beg ) ; for( i = 0; i<40 ; i ++ ) { f.read( (char*)&i, sizeof(int) ) ; cout<<i<<ends; } cout<<endl; } // 打开随机文件 // 先写入 20 个整数 // 记录当前写指针位置值 // 再写入 20 个整数
例7-21 随机文件读写 #include <fstream.h> void main () 例7-21 随机文件读写 7.5.4 二进制文件 #include <fstream.h> void main () { fstream f( "a:DATA.dat" , ios::in | ios::out | ios::binary ) ; int i ; for( i = 0; i < 20 ; i ++ ) f.write((char *)&i, sizeof(int) ) ; long pos = f.tellp() ; for( i = 20; i<40 ; i ++ ) f.write( (char*)&i, sizeof(int) ) ; f.seekg(pos) ; f.read((char*)&i, sizeof(int) ) ; cout << "The data stored is " << i << endl ; f.seekp( 0, ios::beg ) ; for( i = 0; i<40 ; i ++ ) { f.read( (char*)&i, sizeof(int) ) ; cout<<i<<ends; } cout<<endl; } // 打开随机文件 // 先写入 20 个整数 // 记录当前写指针位置值 // 再写入 20 个整数 // 将指针移到 pos 所表示的位置
例7-21 随机文件读写 #include <fstream.h> void main () 例7-21 随机文件读写 7.5.4 二进制文件 #include <fstream.h> void main () { fstream f( "a:DATA.dat" , ios::in | ios::out | ios::binary ) ; int i ; for( i = 0; i < 20 ; i ++ ) f.write((char *)&i, sizeof(int) ) ; long pos = f.tellp() ; for( i = 20; i<40 ; i ++ ) f.write( (char*)&i, sizeof(int) ) ; f.seekg(pos) ; f.read((char*)&i, sizeof(int) ) ; cout << "The data stored is " << i << endl ; f.seekp( 0, ios::beg ) ; for( i = 0; i<40 ; i ++ ) { f.read( (char*)&i, sizeof(int) ) ; cout<<i<<ends; } cout<<endl; } // 打开随机文件 // 先写入 20 个整数 // 记录当前写指针位置值 // 再写入 20 个整数 // 将指针移到 pos 所表示的位置 // 读出一个数据
例7-21 随机文件读写 #include <fstream.h> void main () 例7-21 随机文件读写 7.5.4 二进制文件 #include <fstream.h> void main () { fstream f( "a:DATA.dat" , ios::in | ios::out | ios::binary ) ; int i ; for( i = 0; i < 20 ; i ++ ) f.write((char *)&i, sizeof(int) ) ; long pos = f.tellp() ; for( i = 20; i<40 ; i ++ ) f.write( (char*)&i, sizeof(int) ) ; f.seekg(pos) ; f.read((char*)&i, sizeof(int) ) ; cout << "The data stored is " << i << endl ; f.seekp( 0, ios::beg ) ; for( i = 0; i<40 ; i ++ ) { f.read( (char*)&i, sizeof(int) ) ; cout<<i<<ends; } cout<<endl; } // 打开随机文件 // 先写入 20 个整数 // 记录当前写指针位置值 // 再写入 20 个整数 // 将指针移到 pos 所表示的位置 // 读出一个数据 // 指针移到文件开始
例7-21 随机文件读写 #include <fstream.h> void main () 例7-21 随机文件读写 7.5.4 二进制文件 #include <fstream.h> void main () { fstream f( "a:DATA.dat" , ios::in | ios::out | ios::binary ) ; int i ; for( i = 0; i < 20 ; i ++ ) f.write((char *)&i, sizeof(int) ) ; long pos = f.tellp() ; for( i = 20; i<40 ; i ++ ) f.write( (char*)&i, sizeof(int) ) ; f.seekg(pos) ; f.read((char*)&i, sizeof(int) ) ; cout << "The data stored is " << i << endl ; f.seekp( 0, ios::beg ) ; for( i = 0; i<40 ; i ++ ) { f.read( (char*)&i, sizeof(int) ) ; cout<<i<<ends; } cout<<endl; } // 打开随机文件 // 先写入 20 个整数 // 记录当前写指针位置值 // 再写入 20 个整数 // 将指针移到 pos 所表示的位置 // 读出一个数据 // 指针移到文件开始 // 显示全部数据
例7-21 随机文件读写 #include <fstream.h> void main () 例7-21 随机文件读写 7.5.4 二进制文件 #include <fstream.h> void main () { fstream f( "a:DATA.dat" , ios::in | ios::out | ios::binary ) ; int i ; for( i = 0; i < 20 ; i ++ ) f.write((char *)&i, sizeof(int) ) ; long pos = f.tellp() ; for( i = 20; i<40 ; i ++ ) f.write( (char*)&i, sizeof(int) ) ; f.seekg(pos) ; f.read((char*)&i, sizeof(int) ) ; cout << "The data stored is " << i << endl ; f.seekp( 0, ios::beg ) ; for( i = 0; i<40 ; i ++ ) { f.read( (char*)&i, sizeof(int) ) ; cout<<i<<ends; } cout<<endl; } // 打开随机文件 // 先写入 20 个整数 // 记录当前写指针位置值 // 再写入 20 个整数 // 将指针移到 pos 所表示的位置 // 读出一个数据 // 指针移到文件开始 // 显示全部数据
小结 流对象是内存与文件(或字符串)之间数据传输的信道。 数据流本身没有逻辑格式。数据的解释方式由应用程序的操作决定。流类库 提供了格式化和非格式化的I/O功能。 文本流I/O提供内存基本类型数据与文本之间的格式转换。 处理用户定义的文件I/O要用文件流对象。根据代码方式分为文本文件和二进 制文件,根据数据存取方式分为顺序存取文件和随机存取文件。 文件操作的三个主要步骤是:打开文件;读/写文件;关闭文件流。 文件的性质由打开文件的方式决定。移动流指针,可以对文件的任意位置进 行读/写操作。