15.11 二进制I/O
把数据写到文件时,效率最高的方法是用二进制形式写入。二进制输入避免了在数值转换为字符串的过程中所涉及的开销和精度损失。但二进制数据并非人眼所能阅读,所以只有当数据被另一个程序按顺序读取时,这个技巧才能使用。
fread函数用于读取二进制数据,fwrite函数用于写入二进制数据。它们的原型如下所示:
size_t fread( void *buffer, size_t size, size_t count, FILE *stream );
size_t fwrite( void *buffer, size_t size, size_t count, FILE *stream );
buffer是一个指向用于保存数据的内存位置的指针,size是缓冲区中每个元素的字节数,count是读取或写入的元素数,stream是数据读取或写入的流。
buffer参数被解释为一个或多个值的数组。count参数指定数组中有多少个值,所以读取或写入一个标量时,count的值应为1。函数的返回值是实际读取或写入的元素(并非字节)数目。如果输入过程中遇到了文件尾或者输出过程中出现了错误,这个数字可能比请求的元素数目要小。
让我们观察一个使用这些函数的代码段:
struct VALUE {
long a;
float b;
char c[SIZE];
} values[ARRAY_SIZE];
...
n_values = fread( values, sizeof(struct VALUE), n_values, input_stream );
(处理数组中的数据)
fwrite( value, sizeof( struct VALUE ), n_values, output_stream );
这个程序从一个输入文件读取二进制数据,对它执行某种类型的处理,然后把结果写入到一个输出文件。前面提到,这种类型的I/O效率很高,因为每个值中的位直接从流读取或向流写入,不需要任何转换。
/*
** 二进制I/O。
*/
#include <stdio.h>
#include <stdlib.h>
#define SIZE 20
#define ARRAY_SIZE 5
struct VALUE {
long a;
float b;
char c[SIZE];
} values[ARRAY_SIZE];
int main( void ){
int n_values;
FILE *input_stream;
FILE *output_stream;
values[0] = (struct VALUE){ 1, 1.0, "hello,world" };
values[1] = (struct VALUE){ 2, 2.0, "hello,everyone" };
values[2] = (struct VALUE){ 3, 3.0, "morning" };
values[3] = (struct VALUE){ 4, 4.0, "afternoon" };
values[4] = (struct VALUE){ 5, 5.0, "evening" };
output_stream = fopen( "values.txt", "w" );
if( !output_stream ){
printf( "fail to open values.txt file.\n" );
perror( "reason:" );
exit( EXIT_FAILURE );
}
/*...*/
n_values = fwrite( values, sizeof(struct VALUE), ARRAY_SIZE, output_stream );
printf( "n_values = %d, ARRAY_SIZE = %d\n", n_values, ARRAY_SIZE );
fclose( output_stream );
/*(处理数组中的数据)*/
input_stream = fopen( "values.txt", "r" );
if( !input_stream ){
printf( "fail to open values.txt file.\n" );
perror( "reason:" );
exit( EXIT_FAILURE );
}
n_values = fread( values, sizeof(struct VALUE), n_values, input_stream );
printf( "n_vaues = %d\n", n_values );
int i;
for( i = 0; i < n_values; ++i ){
printf( "%ld, %f, %s\n", values[i].a, values[i].b, values[i].c );
}
fclose( input_stream );
return EXIT_SUCCESS;
}
/* 输出:
*/