60-256 System Programming: Standard Input/Output Library
Content
COMP 2560 System Programming: Standard Input/Output Library
Courtesy of Dr. B. Boufama
modified by Dan Wu
School of Computer Science University of Windsor
Instructor: Dr. Dan Wu
1
Copyright @ 2019, 2020, 2021 all rights reserved
Content
Content
1
2
3
4
5
Introduction
Streams and FILE objects Buffering
Fully buffered I/O Line buffered I/O Unbuffered I/O
ANSI C buffering requirements Changing the default buffering Examples
Opening a Stream
Reading and writing a stream
2
Copyright @ 2019, 2020, 2021 all rights reserved
Introduction Streams and FILE objects
Buffering Opening a Stream
Reading and writing a stream
Introduction
The Standard Input/Output Library was written by Dennis Ritchie around 1975.
This library is specified by the ANSI C standard because it has been implemented on different operating systems.
This library handles details such as
buffer allocation
performing I/O in optimal-sized chunks
The header file of this library is normally in /usr/include/stdio.h
3
Copyright @ 2019, 2020, 2021 all rights reserved
Introduction Streams and FILE objects
Buffering Opening a Stream
Reading and writing a stream
Streams and FILE objects
Opening or creating a file → associating a stream with the file.
fopen()
The function fopen() returns a pointer to the a FILE object. A FILE object is a structure that contains all needed information to manage a stream:
the file descriptor: a nonnegative integer used for the actual I/O
a pointer to a buffer for the stream
the size of the buffer
a count of the characters currently in the buffer
an error flag
an end-of-file flag
Normally, an application software never needs to examine the
FILE object.
4
Copyright @ 2019, 2020, 2021 all rights reserved
Introduction Streams and FILE objects
Buffering Opening a Stream
Reading and writing a stream
Fully buffered I/O Line buffered I/O Unbuffered I/O
ANSI C buffering requirements Changing the default buffering Examples
Buffering
Goal of buffering
Minimize the number of I/O system calls.
There are three types of buffering provided:
fully buffered,
line buffered, unbuffered.
5
Copyright @ 2019, 2020, 2021 all rights reserved
Introduction Streams and FILE objects
Buffering Opening a Stream
Reading and writing a stream
Fully buffered I/O Line buffered I/O Unbuffered I/O
ANSI C buffering requirements Changing the default buffering Examples
Fully buffered I/O
In the case of fully buffered I/O, actual I/O take place only when the I/O buffer is full.
Disk files are fully buffered by the standard I/O library. The buffer is usually created using malloc the first time I/O is performed on a stream.
Flushing buffers
We can call the function fflush() to flush a stream forcing its associated buffer to be written even when it is partially filled.
Syntax:
int fflush(FILE *fp)
When fp is NULL, fflush() causes all output streams to be flushed.
6
Copyright @ 2019, 2020, 2021 all rights reserved
Introduction Streams and FILE objects
Buffering Opening a Stream
Reading and writing a stream
Fully buffered I/O Line buffered I/O Unbuffered I/O
ANSI C buffering requirements Changing the default buffering Examples
Line buffered I/O
In this case of Line buffered I/O, actual I/O takes place only when a new line character is encountered on input or output.
Line buffering is typically used for the standard input and standard output streams.
Actual I/O will also takes place when the line buffer is full before a new line is encountered.
7
Copyright @ 2019, 2020, 2021 all rights reserved
Introduction Streams and FILE objects
Buffering Opening a Stream
Reading and writing a stream
Fully buffered I/O Line buffered I/O Unbuffered I/O
ANSI C buffering requirements Changing the default buffering Examples
Unbuffered I/O
In this case, the standard I/O library does not buffer the characters.
→ each time we print or read a single character, the actual I/O
operation takes place.
For example, the standard error stream is normally unbuffered.
8
Copyright @ 2019, 2020, 2021 all rights reserved
Introduction Streams and FILE objects
Buffering Opening a Stream
Reading and writing a stream
Fully buffered I/O Line buffered I/O Unbuffered I/O
ANSI C buffering requirements Changing the default buffering Examples
ISO C buffering requirements
ISO C requires the following buffering characteristics:
1
2
Standard I/O are fully buffered if and only if they do not refer to an interactive device.
Standard error is never fully buffered.
9
Copyright @ 2019, 2020, 2021 all rights reserved
Introduction Streams and FILE objects
Buffering Opening a Stream
Reading and writing a stream
Fully buffered I/O Line buffered I/O Unbuffered I/O
ANSI C buffering requirements Changing the default buffering Examples
Changing the default buffering
We can change the default buffering using:
void setbuf(FILE *fp, char *buf);
Must be used before any read/write.
Used to substitute buf in place of the buffer normally allocated by the standard I/O library. The size required of buf is determined by the constant BUFSIZ in stdio.h
If buf is NULL then, buffering is disabled.
10
Copyright @ 2019, 2020, 2021 all rights reserved
Introduction Streams and FILE objects
Buffering Opening a Stream
Reading and writing a stream
Fully buffered I/O Line buffered I/O Unbuffered I/O
ANSI C buffering requirements Changing the default buffering Examples
Changing the default buffering
Finer control on buffering
void setvbuf(FILE *fp, char *buf, int mode, size_t size);
This function can specify which buffering we want depending on the value of mode:
IOFBF: fully buffered IOLBF: line buffered IONBF: unbuffered
When using IONBF, the buf and size arguments are ignored.
11
Copyright @ 2019, 2020, 2021 all rights reserved
Introduction Streams and FILE objects
Buffering Opening a Stream
Reading and writing a stream
Fully buffered I/O Line buffered I/O Unbuffered I/O
ANSI C buffering requirements Changing the default buffering Examples
Example 1
//ex1.c
#include
#include
int i=0;
char line[100]=”Hello, my name No-Name\n”; while(line[i] != ‘\0’){
putchar(line[i++]); sleep(1);
}
}
12
Copyright @ 2019, 2020, 2021 all rights reserved
Introduction Streams and FILE objects
Buffering Opening a Stream
Reading and writing a stream
Fully buffered I/O Line buffered I/O Unbuffered I/O
ANSI C buffering requirements Changing the default buffering Examples
Example 2
//ex2.c
#include
#include
int i=0;
char line[100]=”Hello, my name No-Name\n”; while(line[i] != NULL){
putchar(line[i++]);
fflush(stdout); // flush std output buffer sleep(1);
}
}
13
Copyright @ 2019, 2020, 2021 all rights reserved
Introduction Streams and FILE objects
Buffering Opening a Stream
Reading and writing a stream
Fully buffered I/O Line buffered I/O Unbuffered I/O
ANSI C buffering requirements Changing the default buffering Examples
Example 3
//ex3.c
#include
#include
int main(int argc, char *argv[]){ while(1){
printf(“Hello, program is runing right now”); sleep(1);
}
}
14
Copyright @ 2019, 2020, 2021 all rights reserved
Introduction Streams and FILE objects
Buffering Opening a Stream
Reading and writing a stream
Fully buffered I/O Line buffered I/O Unbuffered I/O
ANSI C buffering requirements Changing the default buffering Examples
Example 4
//ex4.c
#include
#include
int main(int argc, char *argv[]){ while(1){
printf(“Hello, program is runing right now\n”); sleep(1);
}
}
15
Copyright @ 2019, 2020, 2021 all rights reserved
16
Q2 part 3 lab 2
Slide 20 lab 1 program hangs?
Open.c
Copyright @ 2019, 2020, 2021 all rights reserved
Introduction A tour of Unix
Summary
Standard Input, Standard Output and Standard Error
#include
int main(int argc, char *argv[]){ FILE *fd;
char c;
if(argc==1) fd=stdin;
else
if((fd = fopen(argv[1], “r”))==NULL){
fprintf(stderr, “Error opening %s, exiting\n”, argv[1]); exit(0);
}
while( (c=getc(fd)) != EOF) putc(c, stdout);
exit(0);
}
17
Copyright @ 2019, 2020, 2021 all rights reserved
18
Copyright @ 2019, 2020, 2021 all rights reserved
Introduction Streams and FILE objects
Buffering Opening a Stream
Reading and writing a stream
Opening a Stream
Three functions can be used to open a standard I/O stream:
FILE *fopen(const char *f, const char *t)
this is the most used one.
Example: file = fopen(‘‘./data.txt’’, ‘‘r’’)
More details on slide 20 for fopen(…)
19
Copyright @ 2019, 2020, 2021 all rights reserved
Introduction Streams and FILE objects
Buffering Opening a Stream
Reading and writing a stream
Opening a Stream
Three functions can be used to open a standard I/O stream:
FILE *freopen(const char *f, const char *t,
FILE *fp)
The freopen function opens a specified file on a specified stream, closing
the stream first if it is already open.
This function is typically used to open a specified file as one
of the predefined streams: standard input, standard output, or standard
error.
if (freopen(“new.input”, “r”, stdin)==NULL)…
20
Copyright @ 2019, 2020, 2021 all rights reserved
Introduction Streams and FILE objects
Buffering Opening a Stream
Reading and writing a stream
Opening a Stream
Three functions can be used to open a standard I/O stream:
FILE *fdopen(int filedesc, const char *t)
This function associates a standard I/O stream with an existing file descriptor (the filedesc argument).
See freopen.c sample code
21
Copyright @ 2019, 2020, 2021 all rights reserved
Introduction Streams and FILE objects
Buffering Opening a Stream
Reading and writing a stream
File descriptors
A file descriptor is a nonnegative integer used by the kernel to specify any open file.
A file descriptor is typically returned by the system call open() that opens/creates a file, a pipe or, a network communication channel.
The function fopen() cannot be used to open a pipe or a network communication channel
→ we use the system call open() to get a file descriptor for
a pipe or a channel, then we use fdopen() to associate it with a standard stream.
22
Copyright @ 2019, 2020, 2021 all rights reserved
Introduction Streams and FILE objects
Buffering Opening a Stream
Reading and writing a stream
Argument types
The argument type, const char *t, specifies how a stream is to be opened.
The possible values of type are :
r for read, w for write, a for append at the end of the file, r+ for read and write, w+ for read and write and, a+ for read and write at the end of the file.
Summary
Restrictions r w a r+ w+ a+
File must exist already ∗ ∗
Previous contents of file lost ∗ ∗
Stream can be read ∗ ∗ ∗ ∗
Stream can be written ∗ ∗ ∗ ∗ ∗
Stream can be written only
at end ∗ ∗
23
Copyright @ 2019, 2020, 2021 all rights reserved
Introduction Streams and FILE objects
Buffering Opening a Stream
Reading and writing a stream
Restrictions
When a file is open for read and write, the following restrictions apply:
Output (reading) cannot be directly followed by input (writing) without an intervening fseek or rewind. Input (writing) cannot be directly followed by output (reading) without an intervening fseek or rewind or, an input operation that encounters an EOF.
int fclose(FILE *fp)
int fclose(FILE *fp) closes any opened stream. In particular:
Any buffered output data is flushed, Any buffered input data is discarded, Any allocated buffer is released.
Note that when a process terminates normally, all open standard I/O streams are closed.
24
Copyright @ 2019, 2020, 2021 all rights reserved
Introduction Streams and FILE objects
Buffering Opening a Stream
Reading and writing a stream
Unformatted I/O
There are 3 types of unformatted I/O: Single-character: I/O
Line I/O: to read or write a line at a time
Direct I/O: also called binary I/O. Useful when dealing with structures and binary information.
25
Copyright @ 2019, 2020, 2021 all rights reserved
Introduction Streams and FILE objects
Buffering Opening a Stream
Reading and writing a stream
Single-character Input functions
int getc(FILE *), int fgetc(FILE *) and
int getchar(void). We have:
getchar(void) is equivalent to getc(stdin). getc() can be implemented as a macro whereas fgetc() cannot.
→ getc is more efficient,
→ the address of fgetc can be passed as a parameter
unlike getc (macros do not have addresses).
Important issues about these functions
They return the next character as an unsigned char converted into an int. Reason: the high order bit is set without causing the return value to be negative.
→ we can read all possible 255 different values of a byte. In
particular, we will never get a character with -1(EOF) as its value.
→ The return value from these functions can’t be stored in a
char variable then compared to EOF
26
Copyright @ 2019, 2020, 2021 all rights reserved
26
Introduction Streams and FILE objects
Buffering Opening a Stream
Reading and writing a stream
Example… (filesize1.c)
#include
int main(int argc, char *argv[]){ FILE *fp;
char ch;
int fileSize=-1;
fd = fopen(argv[1], “r”); do{
ch=getc(fp); fileSize++;
} while( ch != EOF);
printf(“Size of %s is %d\n”, argv[1], fileSize);
}
./size size.c → Size of size.c is 516 (correct size)
Standard Input/Output Library
27
Copyright @ 2019, 2020, 2021 all rights reserved
Introduction Streams and FILE objects
Buffering Opening a Stream
Reading and writing a stream
…Example..(filesize2.c)
However, if the file (example.txt ) you are reading containing special character……
#include
int main(int argc, char *argv[]){ FILE *fd;
char ch;
int fileSize=-1;
fd = fopen(argv[1], “r”); do{
ch=getc(fd); fileSize++;
} while( ch != EOF);
printf(“Size of %s is %d\n”, argv[1], fileSize);
}
./size size.c → Size of size.c is 6 (incorrect size, should be 23)
28
Copyright @ 2019, 2020, 2021 all rights reserved
Introduction Streams and FILE objects
Buffering Opening a Stream
Reading and writing a stream
…Example (filesize3.c)
This can be solved simply by using int instead of char.
#include
int main(int argc, char *argv[]){ FILE *fd;
int ch;
int fileSize=-1;
//y¨
fd = fopen(argv[1], “r”); do{
ch=getc(fd); fileSize++;
} while( ch != EOF);
printf(“Size of %s is %d\n”, argv[1], fileSize);
}
./size size.c → Size of size.c is 259 (correct size)
29
Copyright @ 2019, 2020, 2021 all rights reserved
Introduction Streams and FILE objects
Buffering Opening a Stream
Reading and writing a stream
Note that these 3 functions return -1 whether an error or the end-of-file occurs.
How to differentiate between the 2 situations?
For each stream, two flags are maintained in the FILE object: an error flag and an end-of-file flag.
The following three functions should be used to access these flags:
int ferror(FILE*)
returns nonzero for true, 0 otherwise
int feof(FILE*)
returns nonzero for true, 0 otherwise
void clearerr(FILE*)
clears both the error and the end-of-file flags.
30
Copyright @ 2019, 2020, 2021 all rights reserved
Introduction Streams and FILE objects
Buffering Opening a Stream
Reading and writing a stream
One more example
mycopy.c
31
Copyright @ 2019, 2020, 2021 all rights reserved
Introduction Streams and FILE objects
Buffering Opening a Stream
Reading and writing a stream
Pushing back a character
int ungetc(int c, FILE *fp)
The function int ungetc(int c, FILE *fp)
Return c if OK, -1 otherwise.
This function is used to push back a character after reading from a stream.
This is useful when we need to peek at the next character to determine what to do next.
Note that:
The pushed-back character does not have to be the same as the one that was read.
We cannot push back EOF
We can push back a character after end-of-file is reached. Then, we can read that character because ungetc() clears the end-of-file flag of the stream.
32
Copyright @ 2019, 2020, 2021 all rights reserved
Introduction Streams and FILE objects
Buffering Opening a Stream
Reading and writing a stream
See sample code getchar-putchar.c
Single-character Output functions
int putc(int c, FILE *fp): print a single character int fputc(int c, FILE *fp): same as putc() except that, putc() can be implemented as a macro whereas fputc() cannot.
int putchar(int c): equivalent to putc(c, stdout).
All these functions return the printed character c as an int
when successful and -1 otherwise.
33
Copyright @ 2019, 2020, 2021 all rights reserved
Introduction Streams and FILE objects
Buffering Opening a Stream
Reading and writing a stream
Example
//ex5.c, run it as ./a.out ex5.txt
#include
int main(int argc, char *argv[]){
FILE *f;
char c;
f=fopen(argv[1], “w”); while((c=getchar()) != EOF)
fputc(c, f);
}
Question: what happens if we exit with a CTRL-C?
34
Copyright @ 2019, 2020, 2021 all rights reserved
Introduction Streams and FILE objects
Buffering Opening a Stream
Reading and writing a stream
Example
If this is a serious issue, then we should modify our code to:
#include
int main(int argc, char *argv[]){ FILE *f;
char c;
f=fopen(argv[1], “w”); setbuf(f, NULL); while((c=getchar()) != EOF)
fputc(c, f);
}
or to
#include
int main(int argc, char *argv[]){ FILE *f;
char c;
f=fopen(argv[1], “w”);
while((c=getchar()) != EOF){ fputc(c, f);
fflush(f);
}
}
35
Copyright @ 2019, 2020, 2021 all rights reserved
Introduction Streams and FILE objects
Buffering Opening a Stream
Reading and writing a stream
String/Line Input functions
Input functions:
char *fgets(char *dest, int n, FILE *fp) Reads up through, including, the next newline, but no more than n-1 characters. Then NULL added to whatever has been read.
char *gets(char *dest)
Reads from stdin in a similar way as fgets(), but has some serious side effects. In particular, it allows buffer to overflow. It should never be used!
Note that dest is the address of the array to read the characters into it. Both functions return dest if OK, NULL otherwise (end-of-file or error).
36
Copyright @ 2019, 2020, 2021 all rights reserved
Introduction Streams and FILE objects
Buffering Opening a Stream
Reading and writing a stream
String/Line Output functions
Output functions:
fputs(const char *str, FILE *fp)
Write the NULL terminated string, stored in str, to a stream.
puts(const char *str)
Write the NULL terminated string, stored in str, to stdout
and add a newline character at the end.
Note that NULL character at the end is not written by both functions.
37
See sample code yesno.c
Copyright @ 2019, 2020, 2021 all rights reserved