33-用二进制IO进行随机访问
13.7.9 用二进制I/O进行随机访问
随机访问是用二进制I/O写入二进制文件最常用的方式,我们来看一个简短的例子。程序清单13.6中的程序创建了一个存储 double
类型数字的文件,然后让用户访问这些内容。
程序清单13.6 randbin.c
程序
/* randbin.c -- 用二进制I/O进行随机访问 */
#include <stdio.h>
#include <stdlib.h>
#define ARSIZE 1000
int main()
{
double numbers[ARSIZE];
double value;
const char * file = "numbers.dat";
int i;
long pos;
FILE *iofile;
// 创建一组 double类型的值
for (i = 0; i < ARSIZE; i++)
numbers[i] = 100.0 * i + 1.0 / (i + 1);
// 尝试打开文件
if ((iofile = fopen(file, "wb")) == NULL)
{
fprintf(stderr, "Could not open %s for output.\n", file);
exit(EXIT_FAILURE);
}
// 以二进制格式把数组写入文件
fwrite(numbers, sizeof(double), ARSIZE, iofile);
fclose(iofile);
if ((iofile = fopen(file, "rb")) == NULL)
{
fprintf(stderr,
"Could not open %s for random access.\n", file);
exit(EXIT_FAILURE);
}
// 从文件中读取选定的内容
printf("Enter an index in the range 0-%d.\n", ARSIZE - 1);
while (scanf("%d", &i) == 1 && i >= 0 && i < ARSIZE)
{
pos = (long) i * sizeof(double); // 计算偏移量
fseek(iofile, pos, SEEK_SET); // 定位到此处
fread(&value, sizeof(double), 1, iofile);
printf("The value there is %f.\n", value);
printf("Next index (out of range to quit):\n");
}
// 完成
fclose(iofile);
puts("Bye!");
return 0;
}
首先,该程序创建了一个数组,并在该数组中存放了一些值。然后,程序以二进制模式创建了一个名为 numbers.dat
的文件,并使用 fwrite()
把数组中的内容拷贝到文件中。内存中数组的所有 double
类型值的位组合(每个位组合都是64位)都被拷贝至文件中。不能用文本编辑器读取最后的二进制文件,因为无法把文件中的值转换成字符串。然而,存储在文件中的每个值都与存储在内存中的值完全相同,没有损失任何精确度。此外,每个值在文件中也同样占用64位存储空间,所以可以很容易地计算出每个值的位置。
程序的第2部分用于打开待读取的文件,提示用户输入一个值在数组中的索引。程序通过把索引值和 double
类型值占用的字节相乘,即可得出文件中的一个位置。然后,程序调用 fseek()
定位到该位置,用 fread()
读取该位置上的数据值。注意,这里并未使用转换说明。 fread()
从已定位的位置开始,拷贝8字节到内存中地址为 &value
的位置。然后,使用 printf()
显示 value
。下面是该程序的一个运行示例:
Enter an index in the range 0-999.
500
The value there is 50000.001996.
Next index (out of range to quit):
900
The value there is 90000.001110.
Next index (out of range to quit):
0
The value there is 1.000000.
Next index (out of range to quit):
-1
Bye!