当前位置: 首页 > 文档资料 > C++大学教程 >

14.10 从随机访问文件中顺序地读取数据

优质
小牛编辑
133浏览
2023-12-01

上面几节生成了随机访问文件并将数据写入这个文件中。本节要开发一个程序,顺序读取这个文件.只打印包含数据的记录。该程序还有另一好处,将在本节最后说明,读者不妨先猜猜看。

istream 的函数 read 从指定流的当前位置向对象输入指定字节数。例如,图 14.14 中下列语句:

inCredit.read(reinterpret_cast<char *)(&client),
sizeof(clientData));

从与 ifstrem 的对象 inCredit 相关联的文件中读取sizeof(clientData)指定的字节数,并将数据存放在结构client中。注意函数 read 要求第一个参数类型为 char*。由于 &client 的类型为 clientData *,因此 &client 要用强制类型转换运算符 interpret_cast 变为 char*。注意图 14.14 中的程序中包括图 14.11 定义的头文件 clntdata.h。

1 // Fig. 14.14: figl4_14.cpp
2 // Reading a random access file sequentially
3 #include <iostream.h>
4 #include <iomanip.h>
5 #include <fstream.h>
6 #include <stdlib.h>
7 #include "clntdata.h"
8
9 void outputLine( ostream&, const clientData & );
10
11 int main()
12 {
13 ifstream inCredit( "credit.dat", ios::in );
14
15 if ( !inCredit ) {
16 cerr << "File could not be opened." << endl;
17 exit( 1 );
18 }
19
20 cout << setiosflags( ios::left ) << setw( 10 ) << "Account"
21 << setw( 16 ) << "Last Name" << setw( 11 )
22 << "first Name" << resetiosflags( ios::left )
23 << setw( 10 ) << "Balance" << endl;
24
25 clientData client;
26
27 inCredit.read( reinterpret_cast<char *> ( &client ),
28 sizeof( clientData ) );
29
30 while ( inCredit && !inCredit.eof() ) {
31
32 if { client.accountNumber != 0 )
33 outputLine( cout, client );
34
35 inCredit.read( reinterpret_cast<char *>( &client ),
sizeof( clientData ) );
36
37 }
38
39 return 0;
40 }
41
42 void outputLine( ostream &output, const clientData &c )
43 {
44 output << setiosflags( ios::left ) << setw( 10 )
45 << c.accountNumber << setw( 16 ) << c.lastName
46 << setw( 11 ) << c.firstName << setw( 10 )
47 << setprecision( 2 ) << resetiosflags( ios::left )
48 << setiosflags( ios::fixed | ios::showpoint )
49 << c.balance << '\n';
5O }

输出结果:

Account Last Name First Name Balance
29 Brown Nancy -24.54
33 Dunn Stacey 319.33
37 Barker Doug 9.00
88 Smith Dave 258.34
96 Stone Sam 34.98

图 14.14 从随机访问文件中顺序地读取数据

图 14.14 的程序顺序读取 credit.dat 文件中的每个记录,检查每个记录中是否包含数据,并打印包含数据的记录。第30行的下列条件:

while(inCredit && !inCredit.eof(){

用 ios 成员函数eof确定是否到达文件末尾,如果到达文件末尾,则终止执行while结构。如果读取文件时发生错误,则循环终止,因为inCredit值为false。从文件中输入的数据用outputLine输出,outputLine取两个参数,即ostream对象和要输出的clientData结构。osttream参数类型可以支持任何ostream对象(如cont)或ostream的任何派生类对象(如ofstream类型的对象)作为参数。这样,同一函数既可输出到标准输出流,也可输出到文件流,而不必编写另一个函数。

这些程序还有另一好处,输出窗口中的记录已经按账号排序列出,这是用直接访问方法将这些记录存放到文件中的结果。试比较第4章介绍的冒泡排序,用直接访问方法排序显然快多了。这个速度是通过生成足够大的文件来保证完成每个记录而实现的。当然,大多数时候文件存储都是稀松的,因此会浪费存储空间。这是另一个以空间换取时间的例子:加大空间可以得到更快的排序算法。