[comp.lang.c] fread

Joe_W_Wright@cup.portal.com (05/23/91)

I have a K&R C compiler and would write, as functions, the fread()
and fwrite() routines which don't exist in old C.  [We have only
getc(fp) and putc(c,fp).]

As I understand them, the prototype calls would be:

    fread(&memory, sizeof(object), num_of_objects, fp);

and the function might be:

    int
    fread(buf,size,num,fp) char *buf; int size,num; FILE *fp; {
    }

Questions:

    1.  What is the 'normal' successful return from fread()?
    2.  What if either size or num is 0?
    3.  What if EOF is encountered before num objects are read?
    4.  What if EOF is encountered within an object.

    int
    fwrite(buf,size,num,fp) char *buf; int size,num; FILE *fp; {
    }
    
    5.  What is the successful return from fwrite()?
    6.  What is the 'failure' return? (disk full or whatever)

    7.  As I don't have the 'book' on the subject, what should I
        be reading so that I don't have to ask these simple
        questions on the net anymore?

Thanks to any and all.

Joe_Wright@cup.portal.com

jan@root.co.uk (Joseph Nave) (05/30/91)

In <42589@cup.portal.com> Joe_W_Wright@cup.portal.com writes:


>I have a K&R C compiler and would write, as functions, the fread()
>and fwrite() routines which don't exist in old C.  [We have only
>getc(fp) and putc(c,fp).]

>As I understand them, the prototype calls would be:

>    fread(&memory, sizeof(object), num_of_objects, fp);

>and the function might be:

>    int
>    fread(buf,size,num,fp) char *buf; int size,num; FILE *fp; {
>    }

>Questions: 1 # 7


>Thanks to any and all.

>Joe_Wright@cup.portal.com


You might like to take a look at the XPG3 guide for this function where
all these are answered

	Joe Nave
-- 
"I opened Pandora's box, let the cat out of the bag and 
put the ball in their court"
	Hon. J. Hacker (The Ministry of Administrative Affairs)

shores@fergvax.unl.edu (Shores) (06/25/91)

I'm hoping this problem is only with ultrix.  Let's say I have fopen()ed
a file and the first 2 bytes are 0x0006.  Now on my mac (and a NeXT) I
can say fread (&twoBytes, 2L, 1L, inFile) and it will put the number 6
into a 2 byte integer, like I want.  But when I port this code to a VAX
running ultrix, the same statement puts 0x0600 into the integer! 
 
I would like to post my finished code and have it run on a wide array of
unix machines; are other machines going to give me this problem too, or
is this just because ultrix is acting obnoxious?  I'm about to try to
replace my fread calls with a bunch of ugly getc()s, like create a
getword() which calls getc() twice, and return (char1 << 8) + char2.
I'd sure hate to resort to using this method, so if anyone has any ideas
I would like to hear them (by email).

Thanks!

   Tom... Tommy... Thomas... the Tom-ster, the Tom-boy, the Tomminator...
   ... Tom Shores, Department of Mathematics, University of Nebraska.
   ... shores@fergvax.unl.edu

ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (06/25/91)

In article <shores.677815060@fergvax>, shores@fergvax.unl.edu (Shores) writes:
> I'm hoping this problem is only with ultrix.  Let's say I have fopen()ed
> a file and the first 2 bytes are 0x0006.  Now on my mac (and a NeXT) I
> can say fread (&twoBytes, 2L, 1L, inFile) and it will put the number 6
> into a 2 byte integer, like I want.  But when I port this code to a VAX
> running ultrix, the same statement puts 0x0600 into the integer! 

And so it ruddy well *should*.  That's what you *told* it to do!

You have run into the well known problem that
	+-------------------------------+
	| BINARY FILES ARE NOT PORTABLE |
	+-------------------------------+
A Mac and a NeXT both use members of the MC680x0 family.  You were thus
using essentially the same machine in your first two attempts.

Using 2L and 1L is not portable either, nor is the assumption that there
is such an animal as a "2-byte integer".  (ANSI guarantees that 'short'
is _at least_ 2 bytes, but it might be more.)  What you want to do is

	int nbor_short(short *p, FILE *f)	/* Network Byte Order Read */
	    {					/* Short int		   */
		int c1, c2;
		c1 = getc(f); if (c1 == EOF) return c1;
		c2 = getc(f); if (c2 == EOF) return c2;
		*p = (c1 << 8) + c2;
		return 0;			/* returns 0 for success */
	    }					/* EOF for failure */

or something similar.  I suggest that you do
	% man byteorder
	% man ntohs
on your Ultrix system.  The latter will tell you how
	... fread(&twoBytes, 2, 1, inFile) ...
	twoBytes = ntohs(twoBytes);
is a more portable way to pick up a pair of bytes as a short.  Your NeXT
machine should have these manual entries (and the functions they are about)
too.

This is not the only problem you will have.  The Mac and the NeXT use the
same floating-point format.  VAXes don't.  (VAX floating-point was about
as good as you could get before IEEE.)

-- 
I agree with Jim Giles about many of the deficiencies of present UNIX.

mouse@thunder.mcrcim.mcgill.edu (der Mouse) (06/28/91)

In article <shores.677815060@fergvax>, shores@fergvax.unl.edu (Shores) writes:

> I'm hoping this problem is only with ultrix.

Actually it's a problem with your understanding of multi-byte integers.

> Let's say I have fopen()ed a file and the first 2 bytes are 0x0006.

This doesn't really make sense.  The first two bytes might be 0x00 and
0x06, or 0x06 and 0x00, but to say that they are 0x0006 is at best
misleading.

> Now on my mac (and a NeXT) I can say fread (&twoBytes, 2L, 1L,
> inFile) and it will put the number 6 into a 2 byte integer, like I
> want.  But when I port this code to a VAX running ultrix, the same
> statement puts 0x0600 into the integer!

I guess the first two bytes are 0x00 and 0x06.

This is the famous byte-order problem.  Your fread (or the
corresponding fwrite) is treating an integer as an array of bytes.  How
a multi-byte integer is stored in the various bytes is machine- (and
perhaps compiler-) dependent.  Your Mac and NeXT use so-called
big-endian processors, storing the most-significant 8 bits of the
integer value in the first byte, the next 8 bits next, and so on; the
VAX is what's called little-endian, going the other way around.

> I would like to post my finished code and have it run on a wide array
> of unix machines; are other machines going to give me this problem
> too,

Never never try to move binary files between machines; if you must
write binary files, make sure you read them back on the same machine.
If you really must, use something like XDR to serialize data in a
machine-independent way, or at *least* use ntohl() and friends to
convert integers to a standard byte order.  (Trying to do this with
floats is just asking for trouble.)

> I'm about to try to replace my fread calls with a bunch of ugly
> getc()s, like create a getword() which calls getc() twice, and return
> (char1 << 8) + char2.

That, or something like it, is probably the right approach.  Why do you
dislike it so much?

					der Mouse

			old: mcgill-vision!mouse
			new: mouse@larry.mcrcim.mcgill.edu