14.8 建立随机访问文件
ostream 成员函数 write 把从内存中指定位置开始的固定个数的字节送到指定流中,当流与文件关联时,数据写人到 put 文件位置指针所指示的位置。istream 成员函数 read 把固定个数的字节从指定流输入到内存中指定地址开始的区域。如果流与文件相关联,则该字节从 get 文件位置指针指定的文件地址开始输入。
现在,将整型 number 写入文件时,不是用下列语句:
outFile << number;
对4字节整数打印1位或ll位(10位加一个符号位,各要1字节存储空问),而改用:
outFile.write( reinterpret_cast<const char *>( &number ),
sizeof( number ));
这种方法总是写入4字节(在4字节整数机器上)。write 函数要求一个 const char * 类型的参数为第一个参数,因此我们用reinterpret_cast<const char*>强制类型转换运算符将 number 的地址变为 const char * 指针。write 的第二个参数是 size_t 类型的整数,指定写入的字节数。可以看出,istresm函数read可以将4个字节读回到整型变量number中。
随机存取文件处理程序很少只把一个域写入文件中,通常会一次写入一个结构或一个类对象。
下面举一个例子。
考虑如下的问题描述:
建立一个能够存储100个定长记录的借贷处理系统。每一条记录由账号(用作记录关键字)、姓、名和借贷金额组成。程序要能够更新、插入和删除一条记录以及能够以格式化文本形式列出所有的记录。要求使用随机访问文件。
以下几节介绍了建立借贷处理程序所需的技术。图14.11中的程序说明了怎样打开一个随机访问文件、怎样用struct定义—条记录格式(在cIntdata.h头文件中定义)以及怎样把数据写入磁盘。
程序用write函数和空结构初始化了文件"credit.dat"的所有100条记录。每一个空结构中,账号都为0,姓氏和名为NULL,借贷金额为0.0。文件以这种方式初始化后就在磁盘上建立了存储文件的空间,并且能够确定某条记录是否包含数据。
在图14.11中,下列语句(第34行到第36行):
outCredit.write(
reinterpret cast<const char*>(&blankClient),
将长度为sizeof(clientData)的blankClient结构写入与ofstream的对象outCredit相关联的文件credit.dat。记住,运算符sizeof返回括号中对象的长度(字节数,见第5章)。注意,第34行函数write的第一个参数应为const char*类型,但&blankClient的数据类型为clientData *。要将&blankClient变为相应指针类型,下列表达式:
reinterpret cast<const char *>( &blankClient )
用强制类型转换运算符 reinterpret_cast 将 blankClient 地址变为 const char * 类型,因此调用 write 能顺利编译,而不产生语法错误。
1 // Fig. 14.11: clntdata.h
2 // Definition of struct clientData used in
3 // Figs. 14.11, 14.12, 14.14 and 14.15.
4 #ifndef CLNTDATA_H
5 #define CLNTDATA_H
6
7 struct clientData {
8 int accountNumber;
9 char lastName[15];
10 char firstName[10];
11 float balance;
12 } ;
13
14 #endif
15 // Fig. 14.11: fig14_11.cpp
16 // Creating a randomly accessed file sequentially
17 #include <iostream.h>
18 #include <fstream.h>
19 #include <stdlib.h>
20 #include "clntdata.h"
21
22 int main()
23 {
24 ofstream outCredit( "credit.dat", ios::out );
25
26 if ( !outCredit ) {
27 cerr << "File could not be opened." << endl;
28 exit( 1 );
29 }
3O
31 clientData blankClient = { 0, "", "", 0.0 };
32
33 for ( int i = 0; i < 100; i++ )
34 outCredit.write(
35 reinterpret_cast<const char *>( &blankClient ),
36 sizeof( clientData ) );
37 return 0;
38 }
图 14.11 顺序生成随机访问文件