fgetc() vs. fread()

  • Thread starter M. =?ISO-8859-1?Q?=C5hman?=
  • Start date
M

M. =?ISO-8859-1?Q?=C5hman?=

I'm reading "C: A Reference Manual" but still can't understand a
very basic thing: is there any functional difference between
fgetc/fputc and fread/fwrite (when reading/writing one unsigned
char)?

1. Books and documentation on C tell me fread and fwrite is "binary".
What does binary mean in this? Anything to do with opening a file
in binary mode?

2. I'm also sure I've read somewhere on the net that fread and
fwrite are unbuffered. True or false?

3. I found this when googling:

[ Lawrence Kirby @ comp.lang.c, Sat 5 Feb 2000 ]
....
"In C a stream is a sequence of characters. All read operations are
defined to read data from the stream as if by one or more calls to
fgetc() and all write operations by one or more calls to fputc()."
....

If that's true, I think it would answer the first 2 questions.

Magnus
 
W

Walter Roberson

2. I'm also sure I've read somewhere on the net that fread and
fwrite are unbuffered. True or false?

More false than true. Buffering is a (modifiable) property of the
stream, and applies no matter which of the standard I/O functions
are used to access it.

Possibly what you were looking at was an item about read() and
write() instead of fread() and fwrite(). read() and write() are
very commonly implemented (e.g., Unix, POSIX), but are not part of
the standard C library [and are relatively unlikely ever to
adopted into C itself.]
 
D

Diomidis Spinellis

M. Åhman said:
I'm reading "C: A Reference Manual" but still can't understand a
very basic thing: is there any functional difference between
fgetc/fputc and fread/fwrite (when reading/writing one unsigned
char)?

1. Books and documentation on C tell me fread and fwrite is "binary".
What does binary mean in this? Anything to do with opening a file
in binary mode?

On systems (like Microsoft Windows) that have different conventions for
text and "binary" files opening a file in binary mode will affect both
fread/fwrite and fgetc/fputc. The expalanation for what you've read is
that the fread/fwrite interface is more suited for processing files
containing binary data, whereas the getc/putc interface is more suited
for processing text files.

For example, the Unix dump command reads user data records from the
(binary-structured) utmp file directly into the corresponding utmp
struct using the following fread call:

struct utmp utmp;
if (fread((char *) &utmp, sizeof (struct utmp), 1, f_utmp) != 1)

while the Unix cat command removes successive newlines from
(text-structured) files using the following getc call:

for (prev = '\n'; (ch = getc(fp)) != EOF; prev = ch) {
if (prev == '\n') {
if (ch == '\n') {

Nothing prevents you from processing text files with fread/fwrite (for
example by reading chunks into a large buffer) or binary files with
getc/putc (for example by assembling the data into variables by
hand-crafted code).
 
R

Richard Heathfield

M. Åhman said:

3. I found this when googling:

[ Lawrence Kirby @ comp.lang.c, Sat 5 Feb 2000 ]
...
"In C a stream is a sequence of characters. All read operations are
defined to read data from the stream as if by one or more calls to
fgetc() and all write operations by one or more calls to fputc()."
...

If that's true, I think it would answer the first 2 questions.

When Lawrence Kirby says something about C, you can be more sure of its
accuracy than of your ability to walk in a straight line whilst sober.

From a quick glance at your quote, it looks perfectly correct to me.
 
C

Claude Yih

M. Åhman wrote:

...
"In C a stream is a sequence of characters. All read operations are
defined to read data from the stream as if by one or more calls to
fgetc() and all write operations by one or more calls to fputc()."
...

My conception of fread and fgetc is that fgetc will bring about more
I/O operations between memory and disk because it can only read one
byte into memory at one time while fread reading multiple bytes.

Is my opinion right or wrong?
 
D

Diomidis Spinellis

Claude said:
M. Åhman wrote:



My conception of fread and fgetc is that fgetc will bring about more
I/O operations between memory and disk because it can only read one
byte into memory at one time while fread reading multiple bytes.

Is my opinion right or wrong?

The C input and output streams are typically buffered. A large chunk is
read from (say) the disk into memory with one operation. Functions
like getc, fgetc, fread, and fgets will pick data from that stream until
it is empty, which will cause another transfer from the disk. Calling
fgetc will incur a function call overhead, but, unless you've disabled a
stream's buffering, certainly not the overhead of a disk operation.

Here is an example from an actual implementation of fgetc. _p is a
pointer to the stream's buffer; _r a count of characters remaining in
the buffer, and __srget a function that fills the buffer.

#define __sgetc(p) (--(p)->_r < 0 ? __srget(p) : (int)(*(p)->_p++))

int
fgetc(FILE *fp)
{
return (__sgetc(fp));
}

getc() is typically implemented as a macro, so it won't even incur the
function calling overhead:

#define getc(fp) __sgetc(fp)

On the other hand, in the same implementation, fread will transfer the
data from the stdio buffer to your specified buffer using memcpy, which
can be more efficient than byte-by-byte copies.

size_t
fread(void *buf, size_t size, count, FILE *fp)
{
size_t resid;
char *p;
int r;

if ((resid = count * size) == 0)
return (0);
p = buf;
while (resid > (r = fp->_r)) {
(void)memcpy((void *)p, (void *)fp->_p, (size_t)r);
 
D

Dave Thompson

On systems (like Microsoft Windows) that have different conventions for
text and "binary" files opening a file in binary mode will affect both
fread/fwrite and fgetc/fputc. The expalanation for what you've read is
that the fread/fwrite interface is more suited for processing files
containing binary data, whereas the getc/putc interface is more suited
for processing text files.
Exactly. (And very nicely put.)
For example, the Unix dump command reads user data records from the
(binary-structured) utmp file directly into the corresponding utmp
struct using the following fread call:

struct utmp utmp;
if (fread((char *) &utmp, sizeof (struct utmp), 1, f_utmp) != 1)
dump? Why on Earth should dump care about logins? I don't think it
even cares or cared about userids at all, and if it does or did,
/etc/passwd is not and never was fixed format.
while the Unix cat command removes successive newlines from
(text-structured) files using the following getc call:

for (prev = '\n'; (ch = getc(fp)) != EOF; prev = ch) {
if (prev == '\n') {
if (ch == '\n') {
GNU cat does this (and several other equally silly things) but no
other Unix that I've ever heard of does.
Nothing prevents you from processing text files with fread/fwrite (for
example by reading chunks into a large buffer) or binary files with
getc/putc (for example by assembling the data into variables by
hand-crafted code).

Now that is true.

- David.Thompson1 at worldnet.att.net
 
J

Jordan Abel

Exactly. (And very nicely put.)

dump? Why on Earth should dump care about logins? I don't think it
even cares or cared about userids at all, and if it does or did,
/etc/passwd is not and never was fixed format.

GNU cat does this (and several other equally silly things) but no
other Unix that I've ever heard of does.

You probably haven't heard of any BSD-derived unixes, or at least
haven't heard of this feature. The -s option (to do so) is present on
AFAICT all such systems. FreeBSD's code analogous to those lines is as
follows:

for (prev = '\n'; (ch = getc(fp)) != EOF; prev = ch) {
if (prev == '\n') {
if (sflag) {
if (ch == '\n') {

The flag check has probably been hoisted outside the loop and omitted in
the code that was pasted above.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,955
Messages
2,570,117
Members
46,705
Latest member
v_darius

Latest Threads

Top