09.07.2015 Views

Standard Input/Output Library - University of Windsor

Standard Input/Output Library - University of Windsor

Standard Input/Output Library - University of Windsor

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

Content60-256 System Programming:<strong>Standard</strong> <strong>Input</strong>/<strong>Output</strong> <strong>Library</strong>by Dr. B. BoufamaSchool <strong>of</strong> Computer Science<strong>University</strong> <strong>of</strong> <strong>Windsor</strong>–Instructor: Dr. A. Habedadlane@cs.uwindsor.cahttp://cs.uwindsor.ca/∼adlane/60-256<strong>Standard</strong> <strong>Input</strong>/<strong>Output</strong> <strong>Library</strong>60-256 System Programming


ContentContent1 Introduction2 Streams and FILE objects3 BufferingFully buffered I/OLine buffered I/OUnbuffered I/OANSI C buffering requirementsChanging the default bufferingExamples4 Opening a Stream5 Reading and writing a stream<strong>Standard</strong> <strong>Input</strong>/<strong>Output</strong> <strong>Library</strong>60-256 System Programming


IntroductionStreams and FILE objectsBufferingOpening a StreamReading and writing a streamIntroductionThe <strong>Standard</strong> <strong>Input</strong>/<strong>Output</strong> <strong>Library</strong> was written by DennisRitchie around 1975.This library is specified by the ANSI C standard because it hasbeen implemented on different operating systems.This library handles details such asbuffer allocationperforming I/O in optimal-sized chunksThe header file <strong>of</strong> this library is /usr/include/stdio.h<strong>Standard</strong> <strong>Input</strong>/<strong>Output</strong> <strong>Library</strong>60-256 System Programming


IntroductionStreams and FILE objectsBufferingOpening a StreamReading and writing a streamStreams and FILE objectsOpening 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 neededinformation to manage a stream:the file descriptor: a nonnegative integer used for theactual I/Oa pointer to a buffer for the streamthe size <strong>of</strong> the buffera count <strong>of</strong> the characters currently in the bufferan error flagan end-<strong>of</strong>-file flagNormally, an application s<strong>of</strong>tware never needs to examine theFILE object.<strong>Standard</strong> <strong>Input</strong>/<strong>Output</strong> <strong>Library</strong>60-256 System Programming


BufferingIntroductionStreams and FILE objectsBufferingOpening a StreamReading and writing a streamFully buffered I/OLine buffered I/OUnbuffered I/OANSI C buffering requirementsChanging the default bufferingExamplesGoal <strong>of</strong> bufferingMinimize the number <strong>of</strong> I/O system calls.There are three types <strong>of</strong> buffering provided:fully buffered,line buffered,unbuffered.<strong>Standard</strong> <strong>Input</strong>/<strong>Output</strong> <strong>Library</strong>60-256 System Programming


Fully buffered I/OIntroductionStreams and FILE objectsBufferingOpening a StreamReading and writing a streamFully buffered I/OLine buffered I/OUnbuffered I/OANSI C buffering requirementsChanging the default bufferingExamplesIn the case <strong>of</strong> fully buffered I/O, actual I/O take place onlywhen 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 timeI/O is performed on a stream.Flushing buffersWe can call the function fflush() to flush a stream forcing itsassociated 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 beflushed.<strong>Standard</strong> <strong>Input</strong>/<strong>Output</strong> <strong>Library</strong>60-256 System Programming


Unbuffered I/OIntroductionStreams and FILE objectsBufferingOpening a StreamReading and writing a streamFully buffered I/OLine buffered I/OUnbuffered I/OANSI C buffering requirementsChanging the default bufferingExamplesIn this case, the standard I/O library does not buffer thecharacters.→ each time we print or read a single character, the actual I/Ooperation takes place.For example, the standard error stream is normally unbuffered.<strong>Standard</strong> <strong>Input</strong>/<strong>Output</strong> <strong>Library</strong>60-256 System Programming


IntroductionStreams and FILE objectsBufferingOpening a StreamReading and writing a streamANSI C buffering requirementsFully buffered I/OLine buffered I/OUnbuffered I/OANSI C buffering requirementsChanging the default bufferingExamplesANSI C requires the following buffering characteristics:1 <strong>Standard</strong> I/O are fully buffered if and only if they do notrefer to an interactive device.2 <strong>Standard</strong> error is never fully buffered.<strong>Standard</strong> <strong>Input</strong>/<strong>Output</strong> <strong>Library</strong>60-256 System Programming


IntroductionStreams and FILE objectsBufferingOpening a StreamReading and writing a streamChanging the default bufferingFully buffered I/OLine buffered I/OUnbuffered I/OANSI C buffering requirementsChanging the default bufferingExamplesWe can change the default buffering using:void setbuf(FILE *fp, char *buf);If buf is NULL then, buffering is disabled.Otherwise, buf must point to a buffer <strong>of</strong> length BUFSIZ.void setvbuf(FILE *fp, char *buf, int mode,size t size);This function can specify which buffering we wantdepending on the value <strong>of</strong> mode:IOFBF: fully bufferedIOLBF: line bufferedIONBF: unbufferedNote that when an unbuffered stream is specified, the bufand size arguments are ignored.<strong>Standard</strong> <strong>Input</strong>/<strong>Output</strong> <strong>Library</strong>60-256 System Programming


Example 1IntroductionStreams and FILE objectsBufferingOpening a StreamReading and writing a streamFully buffered I/OLine buffered I/OUnbuffered I/OANSI C buffering requirementsChanging the default bufferingExamples#include #include // This is needed for sleep()int main(void){ // without fflushint i=0;char line[100]="Hello, my name No-Name\n";while(line[i] != NULL){putchar(line[i++]);sleep(1);}}<strong>Standard</strong> <strong>Input</strong>/<strong>Output</strong> <strong>Library</strong>60-256 System Programming


Example 2IntroductionStreams and FILE objectsBufferingOpening a StreamReading and writing a streamFully buffered I/OLine buffered I/OUnbuffered I/OANSI C buffering requirementsChanging the default bufferingExamples#include #include // This is needed for sleep()int main(void){// forcing the flush with fflushint i=0;char line[100]="Hello, my name No-Name\n";while(line[i] != NULL){putchar(line[i++]);fflush(stdout); // flush std output buffersleep(1);}}<strong>Standard</strong> <strong>Input</strong>/<strong>Output</strong> <strong>Library</strong>60-256 System Programming


Example 3IntroductionStreams and FILE objectsBufferingOpening a StreamReading and writing a streamFully buffered I/OLine buffered I/OUnbuffered I/OANSI C buffering requirementsChanging the default bufferingExamples#include #include // needed for sleep()int main(int argc, char *argv[]){}while(1){printf("Hello, program is runing right now");sleep(1);}<strong>Standard</strong> <strong>Input</strong>/<strong>Output</strong> <strong>Library</strong>60-256 System Programming


Opening a StreamIntroductionStreams and FILE objectsBufferingOpening a StreamReading and writing a streamThree 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’’)FILE *freopen(const char *f, const char *t,FILE *fp)Opens a specified file on a specified stream, closing thestream first if it was already open.FILE *fdopen(int filedesc, const char *t)This function associates a standard I/O stream with anexisting file descriptor (the filedesc argument).<strong>Standard</strong> <strong>Input</strong>/<strong>Output</strong> <strong>Library</strong>60-256 System Programming


File descriptorsIntroductionStreams and FILE objectsBufferingOpening a StreamReading and writing a streamA file descriptor is a nonnegative integer used by thekernel to specify any open file.A file descriptor is typically returned by the system callopen() that opens/creates a file, a pipe or, a networkcommunication channel.The function fopen() cannot be used to open a pipe or anetwork communication channel→ we use the system call open() to get a file descriptor fora pipe or a channel, then we use fdopen() to associate itwith a standard stream.<strong>Standard</strong> <strong>Input</strong>/<strong>Output</strong> <strong>Library</strong>60-256 System Programming


Argument typesIntroductionStreams and FILE objectsBufferingOpening a StreamReading and writing a streamThe argument type, const char *t, specifies how a streamis to be opened.The possible values <strong>of</strong> type are :r for read, w for write, a for append at the end <strong>of</strong> the file, r+ forread and write, w+ for read and write and, a+ for read and writeat the end <strong>of</strong> the file.SummaryRestrictions r w a r+ w+ a+File must exist already ∗ ∗Previous contents <strong>of</strong> file lost ∗ ∗Stream can be read ∗ ∗ ∗ ∗Stream can be written ∗ ∗ ∗ ∗ ∗Stream can be written only ∗ ∗at end<strong>Standard</strong> <strong>Input</strong>/<strong>Output</strong> <strong>Library</strong>60-256 System Programming


RestrictionsIntroductionStreams and FILE objectsBufferingOpening a StreamReading and writing a streamWhen a file is open for read and write, the following restrictionsapply:<strong>Output</strong> cannot be directly followed by input without anintervening fflush, fseek, fsetpos, or rewind.<strong>Input</strong> cannot be directly followed by output without anintervening fseek, fsetpos, rewind or, an inputoperation that encounters an EOF.int fclose(FILE *fp)int fclose(FILE *fp) closes any opened stream. Inparticular: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 openstandard I/O streams are closed.<strong>Standard</strong> <strong>Input</strong>/<strong>Output</strong> <strong>Library</strong>60-256 System Programming


Unformatted I/OIntroductionStreams and FILE objectsBufferingOpening a StreamReading and writing a streamThere are 3 types <strong>of</strong> unformatted I/O:Single-character I/OLine I/O: to read or write a line at a timeDirect I/O: also called binary I/O. Useful when dealing withstructures and binary information.<strong>Standard</strong> <strong>Input</strong>/<strong>Output</strong> <strong>Library</strong>60-256 System Programming


IntroductionStreams and FILE objectsBufferingOpening a StreamReading and writing a streamSingle-character <strong>Input</strong> functionsint getc(FILE *), int fgetc(FILE *) andint getchar(void).We have:getchar(void) is equivalent to getc(stdin).getc() can be implemented as a macro whereasfgetc() cannot.→ getc is more efficient,→ the address <strong>of</strong> fgetc can be passed as a parameterunlike getc (macros do not have addresses).Important issues about these functionsThey return the next character as an unsigned charconverted into an int. Reason: the high order bit is set withoutcausing the return value to be negative.→ we can read all possible 255 different values <strong>of</strong> a byte. Inparticular, we will never get a character with -1(EOF) as itsvalue.→ The return value from these functions can’t be stored in achar variable then compared to EOF<strong>Standard</strong> <strong>Input</strong>/<strong>Output</strong> <strong>Library</strong>60-256 System Programming


Example...IntroductionStreams and FILE objectsBufferingOpening a StreamReading and writing a stream#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 <strong>of</strong> %s is %d\n", argv[1], fileSize);./size size.c → Size <strong>of</strong> size.c is 242 (correct size)<strong>Standard</strong> <strong>Input</strong>/<strong>Output</strong> <strong>Library</strong>60-256 System Programming


...ExampleIntroductionStreams and FILE objectsBufferingOpening a StreamReading and writing a streamThis can be solved simply by using int instead <strong>of</strong> char.#include int main(int argc, char *argv[]){FILE *fd;int ch;int fileSize=-1;//ÿfd = fopen(argv[1], "r");do{ch=getc(fd);fileSize++;} while( ch != EOF);printf("Size <strong>of</strong> %s is %d\n", argv[1], fileSize);}./size size.c → Size <strong>of</strong> size.c is 259 (correct size)<strong>Standard</strong> <strong>Input</strong>/<strong>Output</strong> <strong>Library</strong>60-256 System Programming


IntroductionStreams and FILE objectsBufferingOpening a StreamReading and writing a streamNote that these 3 functions return -1 whether an error or theend-<strong>of</strong>-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-<strong>of</strong>-file flag.The following three functions should be used to access theseflags:int ferror(FILE*)returns nonzero for true, 0 otherwiseint fe<strong>of</strong>(FILE*)returns nonzero for true, 0 otherwisevoid clearerr(FILE*)clears both the error and the end-<strong>of</strong>-file flags.<strong>Standard</strong> <strong>Input</strong>/<strong>Output</strong> <strong>Library</strong>60-256 System Programming


IntroductionStreams and FILE objectsBufferingOpening a StreamReading and writing a streamPushing back a characterint 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 readingfrom a stream.This is useful when we need to peek at the next character todetermine what to do next.Note that:The pushed-back character does not have to be the sameas the one that was read.We cannot push back EOFWe can push back a character after end-<strong>of</strong>-file is reached.Then, we can read that character because ungetc() clearsthe end-<strong>of</strong>-file flag <strong>of</strong> the stream.<strong>Standard</strong> <strong>Input</strong>/<strong>Output</strong> <strong>Library</strong>60-256 System Programming


IntroductionStreams and FILE objectsBufferingOpening a StreamReading and writing a streamSingle-character <strong>Output</strong> functionsint putc(int c, FILE *fp): print a single characterint fputc(int c, FILE *fp): same as putc()except that, putc() can be implemented as a macrowhereas fputc() cannot.int putchar(int c): equivalent to putc(c, stdin).All these functions return the printed character c as an intwhen successful and -1 otherwise.<strong>Standard</strong> <strong>Input</strong>/<strong>Output</strong> <strong>Library</strong>60-256 System Programming


ExampleIntroductionStreams and FILE objectsBufferingOpening a StreamReading and writing a stream#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?<strong>Standard</strong> <strong>Input</strong>/<strong>Output</strong> <strong>Library</strong>60-256 System Programming


ExampleIntroductionStreams and FILE objectsBufferingOpening a StreamReading and writing a streamIf 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);}}<strong>Standard</strong> <strong>Input</strong>/<strong>Output</strong> <strong>Library</strong>60-256 System Programming


IntroductionStreams and FILE objectsBufferingOpening a StreamReading and writing a streamString/Line <strong>Input</strong> functions<strong>Input</strong> functions:char *fgets(char *dest, int n, FILE *fp)Reads up through, including, the next newline, but no morethan n-1 characters. Then NULL added to whatever hasbeen read.char *gets(char *dest)Reads from stdin in a similar way as fgets(), but hassome serious side effects. In particular, it allows buffer tooverflow. It should never be used!Note that dest is the address <strong>of</strong> the array to read thecharacters into it. Both functions return dest if OK, NULLotherwise (end-<strong>of</strong>-file or error).<strong>Standard</strong> <strong>Input</strong>/<strong>Output</strong> <strong>Library</strong>60-256 System Programming


IntroductionStreams and FILE objectsBufferingOpening a StreamReading and writing a streamString/Line <strong>Output</strong> functions<strong>Output</strong> functions:fputs(const char *str, FILE *fp)Write the NULL terminated string, stored in str, to astream.puts(const char *str)Write the NULL terminated string, stored in str, to stdoutand add a newline character at the end.Note that NULL character at the end is not written by bothfunctions.<strong>Standard</strong> <strong>Input</strong>/<strong>Output</strong> <strong>Library</strong>60-256 System Programming

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!