Node:Block input and output, Next:File position, Previous:Closing a file, Up:High-level file routines
You can use the two functions in this section, fread
and
fwrite
, to read and write text in blocks of fixed size, rather
than by line or character. You can also use these two functions to read
and write blocks of binary data. This feature is useful if you want to
read and write data in the same format used by your program. For
example, you can store an entire multidimensional array of
floating-point variables in a file with the fwrite
command, then
read it back in directly later with the fread
command, without
any loss of precision caused by converting the floats to strings for use
with the fprintf
function, for example. (The main drawback to
using binary files rather than formatted ASCII text files is that you
cannot easily read and edit the files you create with a text editor.)
For example, to write an array called my_array
, containing
object_count
data objects (such as integers), each of size
object_size
, to the stream my_stream
, you might use the
following line of code:
fwrite (&my_array, object_size, object_count, my_stream);
To read my_array
back from my_stream
, you might then use
the following line:
fread (&my_array, object_size, object_count, my_stream);
Here is a short table to help you remember the directions in which
fwrite
and fread
work.
fwrite
fread
The fwrite
function takes four parameters. The first parameter
to fwrite
is a void pointer (void *
) to an array that
contains the data that will be written to the file. The second
parameter is a variable of type size_t
specifying the size of
each object to be written, and the third parameter, also of type
size_t
, specifies the number of those objects that are to be
written. The final parameter is the stream to be written to (type
FILE *
). If the value returned by fopen
does not match
the third parameter passed (that is, the number of objects to be
written), then there was an error.
Like fwrite
, the fread
function takes four parameters.
Its first parameter is a void pointer to the array that will be written
to. Its second parameter, of type size_t
, specifies how large
each object to be read is, and its third parameter, of type
size_t
, specifies how many of each object is to be read. The
last parameter is simply the stream to read from. Again, if the return
value of this function does not match the third parameter, which
specifies how many object were to be read, there was an error.
Here is an example that creates an array and fills it with multiples of 2,
prints it out, writes the array's data to a file with fwrite
, zeroes the
array and prints it out, reads the data from the file back into the array with
fread
, then prints the array out again so you can compare its data
with the first set of data.
#include <stdio.h> int main() { int row, column; FILE *my_stream; int close_error; char my_filename[] = "my_numbers.dat"; size_t object_size = sizeof(int); size_t object_count = 25; size_t op_return; int my_array[5][5] = { 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50 }; printf ("Initial values of array:\n"); for (row = 0; row <= 4; row++) { for (column = 0; column <=4; column++) { printf ("%d ", my_array[row][column]); } printf ("\n"); } my_stream = fopen (my_filename, "w"); op_return = fwrite (&my_array, object_size, object_count, my_stream); if (op_return != object_count) { printf ("Error writing data to file.\n"); } else { printf ("Successfully wrote data to file.\n"); } /* Close stream; skip error-checking for brevity of example */ fclose (my_stream); printf ("Zeroing array...\n"); for (row = 0; row <= 4; row++) { for (column = 0; column <=4; column++) { my_array[row][column] = 0; printf ("%d ", my_array[row][column]); } printf ("\n"); } printf ("Now reading data back in...\n"); my_stream = fopen (my_filename, "r"); op_return = fread (&my_array, object_size, object_count, my_stream); if (op_return != object_count) { printf ("Error reading data from file.\n"); } else { printf ("Successfully read data from file.\n"); } for (row = 0; row <= 4; row++) { for (column = 0; column <=4; column++) { printf ("%d ", my_array[row][column]); } printf ("\n"); } /* Close stream; skip error-checking for brevity of example */ fclose (my_stream); return 0; }
If all goes well, the code example above will produce the following output:
Initial values of array: 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50 Successfully wrote data to file. Zeroing array... 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 Now reading data back in... Successfully read data from file. 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50
If you attempt to view the file my_numbers.dat
produced by the
program above with a GNU command such as more numbers.dat
, you
will see only garbage, because the information is stored in binary
format, not readable by humans. After attempting to view this binary
file, your terminal may continue to show only garbage and you may have
to reset it. You may be able to do this with a menu option (if you are
running gnome-terminal
, for example), or you may have to type
reset
blindly.