[net.lang.c] portable binary io, or, solving the byte order problem

doug@hcr.UUCP (Doug Moen) (10/05/83)

I've read a number of complaints from people who have run into problems
porting binary files from one machine to another, or sending binary
records across a network.   Sooo...

Here's how you can read and write binary files in a machine
independent fashion, without running into the byte order problem,
and without modifying the C language:

	writeb(stream, format, arguments...)
		FILE *stream;
		char *format;

This is similar to fprintf, except that the arguments are chars,
shorts, ints, or longs, and a conversion specification has the form:
	% <n> [+] <c>
where <n> specifies the number of bytes in the integer to be written,
and <c> is one of C, S, I, or L, meaning that the corresponding argument
is a char, short, int, or long.  Writeb writes out each integer with
a standard byte order (ie, high order byte first, low order byte last).
If the optional '+' is present, it indicates
that the integer is signed, and causes sign extension if the integer
needs to be padded to fill the field width.

There is a corresponding routine, readb(), which works like fscanf.
There are also routines called sreadb() and swriteb() which operate
on buffers instead of file pointers, in the manner of sprintf and sscanf.

Additional features can be added, such as this one:
	struct {
		int x;
		long y;
		char z;
	} foobar;

	writeb(stdout, "%{2I,4L,1C}", &foobar);
which is easier to type than:
	writeb(stdout, "%2I%4L%1C", foobar.x, foobar.y, foobar.z);
Or how about a repetition factor for arrays:
	int x[32];
	writeb(stdout, "%[32]4I", x);
Or even a way to read & write floats and doubles in a machine
independent manner.

It is possible to add the printf(3) conversion specifications to writeb,
as there are no conflicts between the two.

Does anybody think this is a good idea?  (or am I off the mark, or
possibly re-inventing the wheel?)
Are there any further suggestions?  If there is sufficient interest,
I will post a hopefully 'standard' implementation after corresponding
with other people interested in the problem.

stevesu@bronze.UUCP (Steve Summit) (10/06/83)

hcr!doug has a terriffic idea, if portable binary i/o is really
needed.  I don't like binary i/o, and I prefer to use ascii i/o
whenever I can.  It's far more portable that way, and there are
always times when you want to look at the stuff yourself, which
is a real pain if it's binary.  The only reasons I can see for
using binary i/o would be if you're VERY concerned about file
space, or i/o speed, or if you're interfacing with a program that
you can't change which does it that way.
                                         Steve Summit
                                         tektronix!tekmdp!stevesu

dmmartindale@watcgl.UUCP (Dave Martindale) (10/06/83)

Why do you pick the high-byte-first order as the example of a standard?
Low-byte-first seems just as natural, and would be more efficient on
the most common UNIX machines (DEC hardware).

If you are going to produce something really portable, you should come
up with some way of dealing with 6, 7, 9, and 10-bit bytes and word lengths
which may be neither a multiple of 8 nor a multiple of the byte size.

ark@rabbit.UUCP (10/08/83)

Now that you've solved the byte order problem,
how about getting going on the 1's complement problem
and the floating point problem?  Not to mention the
36-bit word problem and the 9-bit byte problem...